Providers¶
ASR backends implement TranscriptionProvider. Cleanup is a separate stage (see Cleanup).
Local (default)¶
| Engine | whisper.cpp via whisper-rs |
| Auth | None |
| GPU | Metal on macOS builds |
| Models | ggml catalogue — aurum models |
| Context | Process-level cache; call clear_context_cache() before exit in long-lived hosts |
| Integrity | Magic check + pinned SHA-256 for common models |
xAI / Grok (JOE-1942 / JOE-1976)¶
| Auth | XAI_API_KEY or [providers.xai] |
| Alias | config/CLI may use grok → canonical xai |
| STT | Official REST POST /v1/stt (product id xai-stt) |
| TTS | Official REST POST /v1/tts (product id xai-tts) |
| Voices | Reviewed: eve | ara | leo | rex | sal |
| Not in this vertical | Realtime/WebSocket voice; OpenAI /audio/* paths; OpenAI voice ids |
Tier is experimental until protected live smoke is retained.
export XAI_API_KEY=...
aurum talk.mp3 --provider xai --model xai-stt
aurum tts "Hello" --provider xai --model xai-tts --voice eve -O /tmp/x.wav
ElevenLabs (TTS only, JOE-1941)¶
| Auth | ELEVENLABS_API_KEY / xi-api-key |
| Path | POST /v1/text-to-speech/{voice_id}?output_format=pcm_24000 |
| Models | Reviewed: eleven_multilingual_v2, eleven_turbo_v2_5, eleven_flash_v2_5 |
| Voice | Required ElevenLabs voice_id (never remapped from Luna/Kitten) |
export ELEVENLABS_API_KEY=...
aurum tts "Hello" --provider elevenlabs \
--model eleven_multilingual_v2 --voice 21m00Tcm4TlvDq8ikWAM -O /tmp/el.wav
Retention/logging is account-dependent; Aurum does not claim zero-retention.
OpenAI (first-party, JOE-1940)¶
| Auth | OPENAI_API_KEY or [providers.openai] |
| STT | Multipart POST /audio/transcriptions (official origin only) |
| TTS | POST /audio/speech (prefer PCM) |
| STT models | Reviewed: whisper-1, gpt-4o-mini-transcribe, gpt-4o-transcribe |
| TTS models | Reviewed: tts-1, tts-1-hd, gpt-4o-mini-tts |
export OPENAI_API_KEY=sk-...
aurum talk.mp3 --provider openai --model whisper-1
aurum tts "Hello" --provider openai --model tts-1 --voice alloy -O /tmp/oai.wav
Independent from OpenRouter: different credential, origin (api.openai.com), and no OpenRouter attribution headers. Audio/text leave the machine only with explicit provider=openai.
OpenRouter¶
| Auth | OPENROUTER_API_KEY (preferred) or config |
| STT paths | Dedicated /audio/transcriptions or multimodal chat (input_audio) |
| TTS path | Dedicated /audio/speech (OpenAI-compatible; JOE-1939) |
| Mode | --openrouter-stt-mode auto\|chat\|transcriptions (default auto) |
| SRT | Only when the route reports reliable timestamps (dedicated ASR) |
| App attribution | Every OpenRouter request sends OpenRouter app headers: HTTP-Referer = https://github.com/joe-broadhead/aurum, X-OpenRouter-Title = Aurum, X-OpenRouter-Categories = audio-gen,cli-agent. Other providers never receive these headers. |
Remote TTS (opt-in)¶
export OPENROUTER_API_KEY=sk-or-...
aurum tts "Hello from OpenRouter" --provider openrouter \
--model hexgrad/kokoro-82m --voice alloy -O /tmp/or.wav --emit-json
- Only reviewed exact OpenRouter TTS model ids are accepted (fail closed). Default:
hexgrad/kokoro-82m(PCM). Other live speech pins includefish-audio/s1,sesame/csm-1b, and MP3-onlyminimax/speech-2.8-turbo(explicit). Dead OpenAI-family OpenRouter ids (e.g.openai/gpt-4o-mini-tts*) are not accepted. - Tier is experimental until a protected live speech smoke is retained; mock CI alone does not promote to supported (JOE-1978).
- Voices are provider voice ids (e.g.
alloy); local Kitten aliases are not remapped. - Wire format is per reviewed record (PCM preferred when the vendor allows it; e.g. MiniMax is MP3-only). Aurum normalizes to mono
i16via the shared remote-audio pipeline. - Privacy: synthesis text is sent to OpenRouter (and potentially an upstream model).
Capability-authoritative auto routing¶
auto does not guess from model-name substrings. It only routes models present in the reviewed static registry (OPENROUTER_STT_REGISTRY in aurum-core). Unknown model ids fail closed with an explicit error — set --openrouter-stt-mode chat or transcriptions yourself for unlisted models.
| Registry class | HTTP path | backend_kind | Timestamps |
|---|---|---|---|
Dedicated ASR (e.g. openai/whisper-large-v3, openai/gpt-4o-transcribe) | /audio/transcriptions | asr | reliable |
Multimodal chat (e.g. google/gemini-2.5-flash) | /chat/completions | llm_assisted | unreliable |
export OPENROUTER_API_KEY=sk-or-...
# Registered multimodal chat model (auto → chat)
aurum talk.mp3 --provider openrouter --model google/gemini-2.5-flash
# Registered dedicated ASR (auto → transcriptions)
aurum talk.mp3 --provider openrouter --model openai/whisper-large-v3 -o srt
# Unregistered model: must choose a path explicitly
aurum talk.mp3 --provider openrouter --model vendor/custom-audio \
--openrouter-stt-mode chat -o json
Privacy settings
OpenRouter account privacy/guardrails must allow the chosen provider, or you will see No endpoints available matching your guardrail restrictions. Configure at https://openrouter.ai/settings/privacy
Long-form remote STT (JOE-2212)
For OpenRouter, OpenAI, and xAI, audio longer than ~210s is time-chunked and stitched automatically (text + segment offsets). Override with AURUM_REMOTE_STT_CHUNK_SECS. Local whisper is unchanged.
flowchart TB
subgraph local [local]
A[PCM 16 kHz mono] --> B[WhisperContext cache]
B --> C[segments + text]
end
subgraph remote [openrouter]
D[encode upload] --> R{auto registry}
R -->|ASR record| E1[/audio/transcriptions]
R -->|chat record| E2[/chat/completions]
R -->|unknown| X[fail closed]
E1 --> F[text + timestamps]
E2 --> G[text LLM-assisted]
end