ALLM.SpeechResponse (allm v0.6.1)

Copy Markdown View Source

A text-to-speech response. Layer A serializable data.

iex> resp = ALLM.SpeechResponse.new(audio: ALLM.Audio.from_binary(<<1, 2>>, "audio/mpeg"), format: :mp3)
iex> ALLM.Audio.size(resp.audio)
{:ok, 2}

Fields

  • :audio: the synthesized audio, as %ALLM.Audio{source: {:binary, bytes}}.
  • :format: the format that arrived, derived from the response's content type through mime_to_format/1. It is not an echo of the request's :format, and the two differ whenever the request left :format as nil. It is nil when the content type is not in the table.
  • :sample_rate: the sample rate in Hz of the audio that arrived, as the adapter reports it, or nil when the adapter cannot tell. For :pcm this is the rate to play the bytes at.
  • :id, :request_id, :model, :provider: provider correlation.
  • :usage: an ALLM.Usage.t/0, never nil. A provider that reports no counters for speech leaves every field nil.
  • :raw: the provider's non-audio body, or nil. Audio bytes are never stored in :raw: they live once, in :audio, so a persisted response does not hold the audio twice. An adapter whose body carries encoded audio replaces it in :raw with a "<N bytes>" placeholder.
  • :metadata: caller-owned.

Format tables

format_to_mime/1 and mime_to_format/1 are the only MIME-to-format tables in the library. They are separate functions so that a provider's extra content type can extend the reverse table without changing the forward one.

:ulaw maps to audio/basic, the registered type for 8 kHz µ-law (RFC 2046), and :alaw to audio/alaw, which has no registered equivalent. ElevenLabs answers ulaw_8000 with audio/ulaw and alaw_8000 with audio/alaw (observed 2026-09-27), so the reverse table also reads audio/ulaw as :ulaw.

Summary

Functions

Map a format atom to its content type.

Map a response content type to a format atom.

Build a %SpeechResponse{} from keyword opts.

Types

t()

@type t() :: %ALLM.SpeechResponse{
  audio: ALLM.Audio.t() | nil,
  format: ALLM.SpeechRequest.format() | nil,
  id: String.t() | nil,
  metadata: map(),
  model: String.t() | nil,
  provider: atom() | nil,
  raw: term(),
  request_id: String.t() | nil,
  sample_rate: pos_integer() | nil,
  usage: ALLM.Usage.t()
}

Functions

format_to_mime(format)

@spec format_to_mime(ALLM.SpeechRequest.format()) :: String.t()

Map a format atom to its content type.

Examples

iex> ALLM.SpeechResponse.format_to_mime(:mp3)
"audio/mpeg"

iex> ALLM.SpeechResponse.format_to_mime(:ulaw)
"audio/basic"

mime_to_format(mime)

@spec mime_to_format(String.t() | nil) :: ALLM.SpeechRequest.format() | nil

Map a response content type to a format atom.

Media-type parameters after ; are stripped and the type is compared case-insensitively. A content type not in the table, or nil, returns nil.

Examples

iex> ALLM.SpeechResponse.mime_to_format("audio/mpeg")
:mp3

iex> ALLM.SpeechResponse.mime_to_format("audio/wav; codecs=1")
:wav

iex> ALLM.SpeechResponse.mime_to_format("audio/ulaw")
:ulaw

iex> ALLM.SpeechResponse.mime_to_format("video/mp4")
nil

new(opts \\ [])

@spec new(keyword()) :: t()

Build a %SpeechResponse{} from keyword opts.

Unknown keys raise KeyError via struct!/2.

Examples

iex> resp = ALLM.SpeechResponse.new(model: "tts-1")
iex> resp.usage
%ALLM.Usage{}