Complete reference for resilient-stt, the local speech transcription orchestrator.
For architecture and pipeline stages, see design.md. For install and
platform notes, see README.md.
| Method | Command |
|---|---|
| PyPI | pip install resilient-stt or pip install "resilient-stt[full]" |
| From source | uv sync --extra full --extra dev in the repo root |
CLI name: resilient-stt (hyphen). Do not use resilient_stt as a shell command.
| Context | How to run |
|---|---|
After pip install |
resilient-stt [OPTIONS] |
| Git checkout | uv run resilient-stt [OPTIONS] or activate .venv and resilient-stt |
| Module (debug) | python -m resilient_stt.orchestrator.main [OPTIONS] |
Package imports use the underscore namespace: resilient_stt.* (see design.md §4).
resilient-stt [OPTIONS]The CLI loads .env from the current working directory on startup (via python-dotenv). Shell
exports take precedence over .env values. See .env.example
for a template.
Exit codes: 0 on success, 1 on pipeline failure (stack trace with -v).
| Flag | Description |
|---|---|
--audio PATH |
Input audio file (any format ffmpeg can decode). |
--output DIR |
Directory for final exports: transcript.json, transcript.srt, transcript.vtt. |
| Flag | Default | Description |
|---|---|---|
-v, --verbose |
off | Enable DEBUG logging (HTTP traces, full exception stacks). |
--work-root DIR |
data/work |
Root for per-run intermediate artifacts (<work-root>/<job_id>/). |
--resume |
off | Reuse existing artifacts under the job work dir when present. |
| Flag | Default | Description |
|---|---|---|
--asr-endpoint URL |
auto | OpenAI-compatible ASR base URL (e.g. http://127.0.0.1:8001/v1). Same as env ASR_BASE_URL / ASR_ENDPOINT. |
--model ID |
see below | ASR model id passed to the endpoint. |
--no-asr-fallback |
off | Do not auto-start the local qwen-asr worker on :8002 when nothing else is reachable. |
--language CODE |
— | Optional BCP-47 language hint (e.g. en, hi). |
--prompt TEXT |
— | Optional ASR prompt for biasing decoding (ignored by OpenRouter STT). |
--asr-provider-label NAME |
external-openai-compatible |
Label stored in transcript metadata; overridden by auto-detection. |
| Endpoint | Default model |
|---|---|
vLLM (:8001) |
Qwen/Qwen3-ASR-1.7B |
Local qwen-asr (:8002) |
Qwen/Qwen3-ASR-0.6B |
OpenAI (api.openai.com) |
whisper-1 |
OpenRouter (openrouter.ai) |
openai/whisper-1 |
| Other OpenAI-compatible | Qwen/Qwen3-ASR-1.7B |
When --asr-endpoint is omitted and ASR_BASE_URL / ASR_ENDPOINT are unset:
--asr-endpointorASR_BASE_URL/ASR_ENDPOINT— explicit URL (always wins).- vLLM at
http://127.0.0.1:8001/v1. - Existing qwen-asr worker at
http://127.0.0.1:8002/v1. - OpenRouter when
OPENROUTER_API_KEYis set, reachable, and--modelis omitted. - OpenAI when
OPENAI_API_KEYis set, reachable, and--modelis omitted. - Start local qwen-asr on
:8002(unless--no-asr-fallback).
Hosted auto-detection (steps 4–5) requires no explicit --model, no
ASR_BASE_URL, and no reachable local ASR. Local ASR is always preferred over
cloud when it responds.
OpenAI — multipart POST /v1/audio/transcriptions. Set OPENAI_API_KEY in
.env or pass via ASR_API_KEY. Auto-fills repair defaults (gpt-4o-mini).
OpenRouter — JSON + base64 audio at POST /api/v1/audio/transcriptions.
Set OPENROUTER_API_KEY or use explicit endpoint:
resilient-stt \
--audio data/input/speech.wav \
--output data/output/run \
--asr-endpoint https://openrouter.ai/api/v1 \
--model openai/whisper-1 \
--skip-diarizationOpenRouter responses are text-only (no segment timestamps). The pipeline sets
weak_timestamps=True, which enables the alignment stage automatically. Use
--align to force alignment even when timestamps exist.
When both OPENROUTER_API_KEY and OPENAI_API_KEY are set, OpenRouter presets
and auto-detection take precedence.
VAD runs on the normalized 16 kHz mono WAV and produces speech regions for
chunking. Music and non-speech audio often yield zero regions — use --no-vad
to transcribe the full file.
| Flag | Default | Description |
|---|---|---|
--no-vad |
off | Disable VAD; treat the entire normalized file as one speech region. |
--vad-backend |
auto |
auto, silero, webrtcvad, or rms. auto: silero → webrtcvad → rms. |
--vad-pad-ms |
250 |
Pad each detected region by this many milliseconds. |
--vad-merge-gap-sec |
0.5 |
Merge regions separated by less than this gap. |
--vad-min-speech-sec |
0.3 |
Minimum region length for webrtcvad / rms backends. |
--vad-min-speech-ms |
1500 |
Silero: minimum speech segment length. |
--vad-min-silence-ms |
500 |
Silero: minimum silence between speech segments. |
When VAD finds no speech, the pipeline logs a warning and exports an empty transcript (zero ASR chunks).
| Flag | Default | Description |
|---|---|---|
--chunk-mode |
fixed |
fixed or pause-aligned. |
--chunk-threshold-sec |
600.0 |
Speech longer than this triggers chunking. |
--chunk-size-sec |
60.0 |
fixed: window size per ASR request. |
--chunk-overlap-sec |
2.0 |
fixed: overlap between consecutive windows. |
--chunk-segment-threshold-sec |
120.0 |
pause-aligned: target split interval at speech onsets. |
--chunk-max-segment-sec |
180.0 |
pause-aligned: hard cap per ASR chunk. |
| Flag | Default | Description |
|---|---|---|
--enhance-audio |
off | Apply high-pass + FFT denoise + loudness normalization during ffmpeg normalize. Useful for fan noise or quiet speech. |
Requires the full or diarization install extra and HF_TOKEN (or a local
model clone). Skip for ASR-only smoke tests.
| Flag | Default | Description |
|---|---|---|
--skip-diarization |
off | Skip pyannote; export without speaker labels. |
--diarization-model |
pyannote/speaker-diarization-community-1 |
Hugging Face model id. |
--diarization-model-path PATH |
— | Local clone path for offline use (see model card). |
--diarization-device |
auto | Device hint: cpu, cuda, or mps. |
--num-speakers N |
— | Exact speaker count hint for pyannote. |
--min-speakers N |
— | Lower bound on speaker count. |
--max-speakers N |
— | Upper bound on speaker count. |
| Flag | Default | Description |
|---|---|---|
--align |
off | Force the optional forced-alignment stage. Also runs automatically when any chunk has weak_timestamps. |
--repair [BOOL] |
see below | Run two-pass LLM transcript repair. |
| Invocation | Behavior |
|---|---|
| omitted | On when OPENROUTER_API_KEY or OPENAI_API_KEY presets apply; off otherwise. |
--repair |
Enable repair. |
--repair true |
Enable repair. |
--repair false |
Disable repair even when API keys are set. |
Accepted boolean strings: true, false, 1, 0, yes, no, on, off.
Repair requires REPAIR_BASE_URL and REPAIR_MODEL (auto-filled from OpenRouter
or OpenAI presets). Repair only modifies segment text; timestamps and speaker
labels are validated and preserved.
Loaded from .env and the shell. CLI flags override config fields where noted.
| Variable | Purpose |
|---|---|
ASR_BASE_URL / ASR_ENDPOINT |
Fixed ASR base URL (same as --asr-endpoint). |
ASR_API_KEY |
Bearer token for ASR requests. |
OPENROUTER_API_KEY |
OpenRouter key; enables OpenRouter presets and auto-detection. |
OPENAI_API_KEY |
OpenAI key; enables OpenAI presets and auto-detection. |
REPAIR_BASE_URL |
OpenAI-compatible chat base URL (e.g. https://api.openai.com/v1). |
REPAIR_MODEL |
Repair model id (e.g. gpt-4o-mini, openai/gpt-4o-mini). |
REPAIR_API_KEY |
Bearer token for repair requests. |
HF_TOKEN |
Hugging Face token for downloading gated pyannote weights. |
Key resolution order for ASR/repair tokens: ASR_API_KEY / REPAIR_API_KEY →
OPENROUTER_API_KEY → OPENAI_API_KEY.
On startup the orchestrator disables optional dependency telemetry by default.
Opt back in via shell or .env:
| Variable | Default | Effect |
|---|---|---|
PYANNOTE_METRICS_ENABLED |
0 |
Set 1 to re-enable pyannote usage metrics. |
HF_HUB_DISABLE_TELEMETRY |
1 |
Set 0 to re-enable Hugging Face Hub telemetry. |
Examples use resilient-stt (as after pip install). From a git checkout, prefix with uv run.
Minimal (local qwen-asr auto-start):
resilient-stt \
--audio data/input/meeting.mp3 \
--output data/output/meeting \
--language hivLLM ASR:
resilient-stt \
--audio data/input/meeting.mp3 \
--output data/output/meeting \
--asr-endpoint http://127.0.0.1:8001/v1 \
--model Qwen/Qwen3-ASR-1.7B \
--language hi \
--repair trueOpenRouter ASR (explicit):
resilient-stt \
--audio data/input/speech.wav \
--output data/output/openrouter \
--asr-endpoint https://openrouter.ai/api/v1 \
--model mistralai/voxtral-mini-transcribe \
--skip-diarization \
--repair falseMusic / non-speech (skip VAD):
resilient-stt \
--audio data/input/music.wav \
--output data/output/music \
--asr-endpoint https://openrouter.ai/api/v1 \
--model google/chirp-3 \
--no-vad \
--enhance-audio \
--skip-diarizationResume after interruption:
resilient-stt \
--audio data/input/meeting.mp3 \
--output data/output/meeting \
--resumeEach run writes under data/work/<job_id>/ (or --work-root):
normalized.wav
speech_regions.json # {regions, speech_onsets_samples}
chunks/ # per-chunk WAV slices
chunks.json
asr_raw/<chunk_id>.json
asr_normalized.json
diarization.json
speaker_segments_raw.json
speaker_segments_repaired.json # when --repair is on
Final exports land under --output.
The CLI is a thin wrapper around resilient_stt.orchestrator.pipeline.run(JobConfig). For
embedding in other tools or services, install the package and use:
from resilient_stt.orchestrator.config import JobConfig
from resilient_stt.orchestrator.pipeline import run
from resilient_stt.asr.endpoint_client import OpenAICompatibleASRProvider
# Build JobConfig (from CLI args or your own), pass an ASRProvider, then:
# run(config, asr_provider)See design.md §1 and §5.10.