ALLM.Providers.Support.ElevenLabs (allm v0.6.1)

Copy Markdown View Source

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:

formatsample_rate accepted (nil picks the default)output_format
:mp3 or nil22050, 24000, 44100 (default)mp3_22050_32, mp3_24000_48, mp3_44100_128
:opus48000 (default)opus_48000_64
:pcm8000, 16000, 22050, 24000 (default), 32000, 44100, 48000pcm_<rate>
:wavthe same rates as :pcm, 24000 by defaultwav_<rate>
:ulaw8000 (default)ulaw_8000
:alaw8000 (default)alaw_8000
:aac, :flacnoneElevenLabs 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

output()

@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

output_format(format, sample_rate)

@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]}}