Text to Speech

Convert text into spoken audio

Table of contents

  1. Basic Speech Generation
  2. Choosing Models
  3. Voices
  4. Formats
  5. Style
  6. Error Handling
  7. Next Steps

After reading this guide, you will know:

  • How to generate speech from text.
  • How to save generated audio files.
  • How to choose models, voices, and formats.
  • How to access raw audio bytes.

Basic Speech Generation

Generate audio with the global RubyLLM.speak method:

speech = RubyLLM.speak "Hello, welcome to RubyLLM!"
speech.save "welcome.mp3"

The return value is a RubyLLM::Speech object:

speech.model
# => "gpt-4o-mini-tts"

speech.voice
# => "alloy"

speech.format
# => "mp3"

speech.mime_type
# => "audio/mpeg"

speech.to_blob
# => raw audio bytes

Choosing Models

By default, RubyLLM uses config.default_speech_model.

RubyLLM.speak("Ship it.", model: "gpt-4o-mini-tts")

RubyLLM.speak(
  "Say cheerfully: Have a wonderful day!",
  model: "gemini-2.5-flash-preview-tts",
  provider: :gemini
)

Configure the default globally:

RubyLLM.configure do |config|
  config.default_speech_model = "gpt-4o-mini-tts"
end

Voices

RubyLLM picks a provider default voice for the simple case. Pass voice: when you want a specific one.

RubyLLM.speak("Welcome back.", voice: "nova")

RubyLLM.speak(
  "Say warmly: Welcome back.",
  provider: :gemini,
  model: "gemini-2.5-flash-preview-tts",
  voice: "Kore"
)

OpenAI voices include alloy, ash, ballad, coral, echo, fable, onyx, nova, sage, shimmer, verse, marin, and cedar. Gemini supports its own voice set, including Kore, Puck, Zephyr, and Sadachbia.

Formats

OpenAI supports several output formats:

speech = RubyLLM.speak("Save this as a WAV file.", format: "wav")
speech.save("voiceover.wav")

Supported OpenAI formats are mp3, opus, aac, flac, wav, and pcm.

Gemini’s generateContent speech endpoint returns raw PCM audio. RubyLLM reports that honestly:

speech = RubyLLM.speak(
  "Say cheerfully: Have a wonderful day!",
  provider: :gemini,
  model: "gemini-2.5-flash-preview-tts"
)

speech.format
# => "pcm"

Convert PCM with a tool like ffmpeg when you need a container format:

ffmpeg -f s16le -ar 24000 -ac 1 -i out.pcm out.wav

Style

RubyLLM.speak keeps the options every provider understands as keywords: model:, voice:, and format:. Provider-specific speech controls go in provider_options:, a hash of options in the provider’s own request vocabulary that RubyLLM merges into the request as-is. OpenAI supports instructions: and speed::

RubyLLM.speak(
  "The build is green.",
  provider_options: {
    instructions: "Speak with calm confidence.",
    speed: 1.1
  }
)

Gemini handles style through the prompt:

RubyLLM.speak(
  "Say in a bright, encouraging voice: The build is green.",
  provider: :gemini,
  model: "gemini-2.5-flash-preview-tts",
  voice: "Puck"
)

Error Handling

begin
  speech = RubyLLM.speak("Hello")
  speech.save("hello.mp3")
rescue RubyLLM::BadRequestError => e
  puts "Invalid request: #{e.message}"
rescue RubyLLM::Error => e
  puts "Speech generation failed: #{e.message}"
end

Next Steps