Skip to main content
audio.cpp is a local C++ audio inference server built on ggml: text-to-speech, speech-to-text, alignment, diarization, separation, and more, across 80+ model families. GoModel has a dedicated audiocpp provider type for it. It is an audio-only provider. /v1/audio/speech and /v1/audio/transcriptions route to it; chat, /responses, and /v1/embeddings return invalid_request_error, because audiocpp_server has no such endpoints. Start the server first, with a config naming the models it serves:

Configure

The base URL is required and registers the provider — audiocpp_server’s default port (8080) collides with GoModel’s own, so there is no default:
AUDIOCPP_API_KEY is optional and usually unset: audio.cpp has no authentication of its own. Set it only when a reverse proxy in front of the server expects a bearer token.
These examples assume GoModel runs in Docker and audio.cpp is on the host — hence host.docker.internal. If GoModel runs on the host directly, use http://localhost:8099. A trailing /v1 is accepted and trimmed, so both spellings address the same server. Running several instances? Register each under a suffixed name: AUDIOCPP_GPU_BASE_URL=... creates provider audiocpp-gpu.

Verify

Voices are audio.cpp names, not OpenAI names

voice names an audio.cpp voice preset, a cached voice id, or a wav in the configured voice library — audio.cpp has no fixed voice set, so OpenAI’s alloy/nova/… mean nothing to it. List what a model offers with GET /p/audiocpp/audio/voices?model=<id>. voice is required on /v1/audio/speech, as it is in the OpenAI API. To let audio.cpp apply a model’s configured default_voice_preset instead, call the route through passthrough: POST /p/audiocpp/audio/speech. Cloning parameters (voice_ref, reference_text, seed, max_tokens, options, …) are forwarded verbatim, so audio.cpp’s own request fields work through the standard endpoint — with one exception, a voice_ref naming a server-side path (see below):

Audio formats

Synthesis returns WAV whatever response_format asked for, unless the server was built with the MP3 frontend module. The response is labelled with the type audio.cpp actually returned (audio/wav), not the one that was requested. Transcription uploads must be WAV; the server rejects other containers unless it was built with the audio_decode frontend module, which adds MP3 and FLAC.

Transcribing without an upload

audio.cpp can also read audio from the machine it runs on, and its live route carries raw PCM with no file at all. Neither shape is offered on /v1/audio/transcriptions: both let the caller choose what the audio.cpp host reads or how long it holds a model, and being authorized for a model is not authorization for either. They stay on the native surface below, which an operator enables deliberately and points only at trusted callers. For the same reason, a voice_ref on /v1/audio/speech must carry inline base64 audio; {"type": "path"} and a bare path string are rejected and available only through passthrough.

Streaming

For a model configured with "mode": "streaming", stream=true returns audio.cpp’s OpenAI-shaped transcript events (transcript.text.delta, transcript.text.done, [DONE]). GoModel relays the event stream as it is, but reads it to completion first, so this shortens nothing end to end — it is the live route below that emits text while the speaker is still talking.

Native endpoints

audio.cpp’s routes with no OpenAI equivalent are reachable through passthrough at /p/audiocpp/..., once an operator opts in:
It is not on by default, unlike most provider types: this surface is opaque, so a request reaching it is not checked against the caller’s model allowlist, and audio.cpp serves model management (/models/load, /tasks/unload_models) and server-local file paths there. Enable it for trusted callers only. The /v1 prefix is optional (/p/audiocpp/audio/voices and /p/audiocpp/v1/audio/voices are the same route); /health is served from the server root. The live route is the one that transcribes speech as it is captured — there is no file, and the audio never has to exist on disk:
-T - is what keeps it live: --data-binary @- drains stdin before opening the connection, which turns the capture back into a file upload. Whether partial text appears during capture is a property of the model, not the route.

Model metadata

GET /v1/models reports what audio.cpp says about each configured model:
  • Family — the audio.cpp model family (pocket_tts, moonshine_asr, …).
  • Modeaudio_speech for a tts model and audio_transcription for an asr one. Models registered for other tasks (align, diarization, separation, …) stay listed without a mode: GoModel has no endpoint to route them to, and they are reached through passthrough instead.
  • Capabilitiesstreaming for a model configured with "mode": "streaming".
These are defaults, not decisions: anything you declare under the provider’s model metadata wins — see Model metadata.
Last modified on September 20, 2026