The half of the ElevenLabs audio adapters that both of them share:
the base URL, the auth header, the output_format mapping, error
classification and key redaction.
Layer B helper, used by ALLM.Providers.ElevenLabs.Speech and
ALLM.Providers.ElevenLabs.Transcription. Each adapter wraps what this
module returns in its own error struct.
Output formats
output_format/2 is the only place that maps a request's format and
sample_rate to ElevenLabs' output_format query value:
format | sample_rate accepted (nil picks the default) | output_format |
|---|---|---|
:mp3 or nil | 22050, 24000, 44100 (default) | mp3_22050_32, mp3_24000_48, mp3_44100_128 |
:opus | 48000 (default) | opus_48000_64 |
:pcm | 8000, 16000, 22050, 24000 (default), 32000, 44100, 48000 | pcm_<rate> |
:wav | the same rates as :pcm, 24000 by default | wav_<rate> |
:ulaw | 8000 (default) | ulaw_8000 |
:alaw | 8000 (default) | alaw_8000 |
:aac, :flac | none | ElevenLabs has no such output |
ulaw_8000 and alaw_8000 are the only G.711 values ElevenLabs lists:
its 403 invalid_output_format answer to an invented ulaw_16000 names
every accepted value, and no other ulaw_ or alaw_ rate is among them
(observed 2026-09-27). The two answer with audio/ulaw and audio/alaw
content types and headerless 8-bit samples.
ElevenLabs gates some formats by subscription tier: pcm_44100 and
wav_44100 need the Pro tier, and the provider answers them on a lower
tier with a 403 (observed 2026-09-26), which classify/2 reports as
:unsupported_feature. The 24,000 Hz defaults for :pcm and :wav avoid
that gate.
Error classification
classify/2 reads the error envelope ElevenLabs sends,
{"detail": {"type", "code", "message", "status", "request_id", "param"?}}
(a 422 sends detail as a list of validation errors instead), and returns
the ALLM reason. An invalid API key is answered with a 400 or a
401 depending on the key's shape (a hex-shaped key got a 400
invalid_api_key, a mixed-case one a 401 unauthorized; observed
2026-09-26), and both carry detail.type: authentication_error, so the
body is read before the status.
Summary
Types
The resolved output of output_format/2.
Functions
Map a speech format and sample_rate to ElevenLabs' output_format.
Types
@type output() :: %{ output_format: String.t(), format: :mp3 | :opus | :pcm | :wav | :ulaw | :alaw, mime_type: String.t(), sample_rate: pos_integer() }
The resolved output of output_format/2.
Functions
@spec output_format(atom() | nil, pos_integer() | nil) :: {:ok, output()} | {:error, {:format, term()} | {:sample_rate, [pos_integer()]}}
Map a speech format and sample_rate to ElevenLabs' output_format.
A nil format is :mp3, the provider's own default, and a nil
sample_rate takes the format's default rate. Returns
{:error, {:format, format}} for a format ElevenLabs cannot produce and
{:error, {:sample_rate, accepted}} for a rate outside the format's set.
Examples
iex> ALLM.Providers.Support.ElevenLabs.output_format(nil, nil)
{:ok, %{output_format: "mp3_44100_128", format: :mp3, mime_type: "audio/mpeg", sample_rate: 44_100}}
iex> {:ok, out} = ALLM.Providers.Support.ElevenLabs.output_format(:pcm, 16_000)
iex> out.output_format
"pcm_16000"
iex> ALLM.Providers.Support.ElevenLabs.output_format(:ulaw, nil)
{:ok, %{output_format: "ulaw_8000", format: :ulaw, mime_type: "audio/basic", sample_rate: 8_000}}
iex> ALLM.Providers.Support.ElevenLabs.output_format(:flac, nil)
{:error, {:format, :flac}}
iex> ALLM.Providers.Support.ElevenLabs.output_format(:opus, 24_000)
{:error, {:sample_rate, [48_000]}}