| name | speech-recognition |
|---|---|
| description | Transcribe audio files to text (speech recognition / ASR) using the Z.ai GLM-ASR model. Use whenever the user wants to transcribe, caption, or convert spoken audio (mp3, wav, m4a, flac, ogg, etc.) into text, or asks "what does this audio say". |
Claude has no native audio input, so use the Z.ai glm-asr-2512 model to turn an audio
file into text. It's one curl call — inlined below, no helper script. Needs curl and jq.
The API key is ZAI_TOKEN, exported by ~/.zsh_aliases. Source it once per shell:
source ~/.zsh_aliasessource ~/.zsh_aliases
curl -sS --request POST \
--url https://api.z.ai/api/paas/v4/audio/transcriptions \
--header "Authorization: Bearer $ZAI_TOKEN" \
--form model=glm-asr-2512 \
--form stream=false \
--form file=@<audio-file> | jq -r '.text'Optional --form fields:
prompt=<text>— context to bias style/language. GLM-ASR has no language parameter (it auto-detects); pass a short prompt in the target language to nudge detection, e.g.--form prompt="Transcripción en español.".hotwords=<json-array>— domain vocabulary (names, jargon) to improve accuracy, max 100, as a JSON array string:--form hotwords='["Anthropic","Claude"]'.
Full example:
source ~/.zsh_aliases
curl -sS --request POST \
--url https://api.z.ai/api/paas/v4/audio/transcriptions \
--header "Authorization: Bearer $ZAI_TOKEN" \
--form model=glm-asr-2512 \
--form stream=false \
--form file=@<audio-file> \
--form prompt="Transcripción en español." \
--form hotwords='["Anthropic","Claude"]' | jq -r '.text'On failure the API returns a JSON error body (e.g. {"error":{"code":"1214",...}}); drop the
| jq -r '.text' to see it raw. For incremental output set --form stream=true and parse the
data: SSE lines instead of piping to jq.
Limits: .wav/.mp3 only, max 25 MB and 30 seconds per file. Split longer audio before sending.
The API accepts only .wav/.mp3 and returns {"code":"1214","message":"...file format is not supported..."} for anything else. Telegram voice notes are Ogg/Opus (document_* with no extension); convert first. macOS afconvert can't decode Opus and ffmpeg/brew are often absent — if so, convert inside a container (OrbStack/Docker is usually available):
docker run --rm -v "$PWD":/work -w /work mcr.microsoft.com/devcontainers/base:ubuntu26.04 bash -c '
export DEBIAN_FRONTEND=noninteractive
apt-get update -qq && apt-get install -y -qq ffmpeg
ffmpeg -y -i in.ogg -ar 16000 -ac 1 out.wav' # ffprobe -show_entries format=duration to check <30sGLM-ASR has no language override, and on short/noisy clips its auto-detect can lock onto the wrong language (e.g. a 4s Spanish voice note transcribed as Chinese) — prompt and hotwords alone do not fix this. What reliably unblocks detection is padding silence at both the start and end plus loudness normalization, then re-running:
ffmpeg -y -i in.ogg -af "apad=pad_dur=1,adelay=1000|1000,loudnorm" -ar 16000 -ac 1 out.wavRun 2–3 passes and check the result is stable. If it still won't converge, the clip is genuinely hard — try splitting it in half. Normalize/highpass/tempo tweaks alone did not help; the start+end padding is the key lever.