Skip to main content

deepgram-rust-text-to-speech

Use when implementing Deepgram text-to-speech in the Rust SDK, including Aura and Flux TTS model selection, speak feature flags, output file or byte-stream handling, the streaming Aura and Flux TTS WebSocket handles, and real crate APIs under speak::options, speak::flux, and Speak.

Source facts

Repository
deepgram/deepgram-rust-sdk
Last source activity
October 8, 2026 at 12:36
Detected SKILL.md language
English
Stars
67
Forks
45

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
deepgram-rust-text-to-speech
description
Use when implementing Deepgram text-to-speech in the Rust SDK, including Aura and Flux TTS model selection, speak feature flags, output file or byte-stream handling, the streaming Aura and Flux TTS WebSocket handles, and real crate APIs under speak::options, speak::flux, and Speak.
# Using Deepgram Text-to-Speech (Rust SDK) Use this skill when generating audio from text with the Rust SDK's `Speak` surface. ## When to use this product - Converting text into audio files with `speak_to_file(...)`. - Streaming TTS bytes with `speak_to_stream(...)`. - Capturing the `dg-request-id` Deepgram support asks for (plus model name/uuid, character count, content type) with `speak_to_file_with_metadata(...)` / `speak_to_stream_with_metadata(...)`, which return a `SpeakMetadata` alongside the audio. Every field is optional, so read it through `metadata.request_id()`. - Selecting Aura voices and output encodings with `speak::options::Options`. - Streaming text in and audio out over the Aura WebSocket with `speak_stream().handle()` — the shape to use when the text comes from an LLM and the audio goes to a player. - Synthesizing with Flux TTS (`/v2/speak`) in batch with `flux_speak_to_file(...)` or `flux_speak_to_stream(...)`, or turn by turn over the WebSocket with `flux_request(options).handle()`. ## Authentication For a TTS-only install: ```toml [dependencies] deepgram = { version = "0.12", default-features = false, features = ["speak"] } tokio = { version = "1", features = ["full"] } futures = "0.3" # Only add `bytes = "1"` if you need to name `bytes::Bytes` in your own signatures. # The code below relies on type inference and does not import bytes directly. ``` ```rust let dg = deepgram::Deepgram::new(std::env::var("DEEPGRAM_API_KEY")?)?; ``` - API keys use `Authorization: Token <api_key>`. - Aura text-to-speech (`/v1/speak`) has both transports: REST (`Speak::speak_to_file` / `speak_to_stream`, a saved file or a stream of bytes) and the WebSocket (`Speak::speak_stream().handle()`, returning a `SpeakStreamHandle`: `speak`, `flush`, `clear`, `close`, `receive`, plus `split` / `sender` for sending and receiving from different tasks). Flux TTS (`/v2/speak`) likewise has both, in the `speak::flux` module: `Speak::flux_speak_to_file` / `flux_speak_to_stream` for batch and `Speak::flux_request(options).handle()` for the streaming WebSocket (`FluxSpeakHandle`: `speak`, `flush`, `interrupt`, `configure_speed`, `close`, `receive`). ## Quick start ## Quick start: save audio to a file ```rust use std::{path::Path, time::Instant}; use deepgram::{ speak::options::{Container, Encoding, Model, Options}, Deepgram, }; #[tokio::main] async fn main() -> Result<(), Box<dyn std::error::Error>> { let api_key = std::env::var("DEEPGRAM_API_KEY")?; let dg = Deepgram::new(&api_key)?; let options = Options::builder() .model(Model::AuraAsteriaEn) .encoding(Encoding::Linear16) .sample_rate(16000) .container(Container::Wav) .build(); let start = Instant::now(); dg.text_to_speech() .speak_to_file("Hello from Rust.", &options, Path::new("output.wav")) .await?; println!("Time to download audio: {:.2?}", start.elapsed()); Ok(()) } ``` ## Quick start: stream response bytes ```rust use deepgram::{ speak::options::{Container, Encoding, Model, Options}, Deepgram, }; use futures::stream::StreamExt; #[tokio::main] async fn main() -> Result<(), Box<dyn std::error::Error>> { let api_key = std::env::var("DEEPGRAM_API_KEY")?; let dg = Deepgram::new(&api_key)?; let options = Options::builder() .model(Model::AuraAsteriaEn) .encoding(Encoding::Linear16) .sample_rate(16000) .container(Container::Wav) .build(); let mut stream = dg .text_to_speech() .speak_to_stream("Hello from Rust.", &options) .await?; while let Some(chunk) = stream.next().await { println!("received {} bytes", chunk.len()); } Ok(()) } ``` ## Quick start: Aura streaming (WebSocket) ```rust use deepgram::{ speak::{ options::{Encoding, Model}, SpeakResponse, }, Deepgram, }; #[tokio::main] async fn main() -> Result<(), Box<dyn std::error::Error>> { let api_key = std::env::var("DEEPGRAM_API_KEY")?; let dg = Deepgram::new(&api_key)?; // The streaming endpoint emits raw audio only: linear16, mulaw, or alaw. let handle = dg .text_to_speech() .speak_stream() .model(Model::Aura2ThaliaEn) .encoding(Encoding::Linear16) .sample_rate(24_000) .handle() .await?; // Split so text can be sent while audio is still arriving. let (sender, mut events) = handle.split(); let producer = tokio::spawn(async move { for piece in ["Hello, ", "this is streaming text to speech."] { sender.speak(piece).await?; } sender.flush().await?; sender.close().await }); while let Some(message) = events.receive().await { match message? { SpeakResponse::Audio(_chunk) => { /* play or buffer the audio */ } SpeakResponse::Flushed { .. } => { /* the flushed segment is complete */ } SpeakResponse::Warning { description, .. } => { eprintln!("warning: {description:?}"); } _ => {} } } producer.await.expect("producer task panicked")?; Ok(()) } ``` `clear()` discards text the server has not synthesized yet — use it on barge-in. See `examples/speak/websocket/text_to_speech_websocket.rs` for the full loop, including writing the audio to a file. ## Quick start: Flux TTS batch (REST) ```rust use std::path::Path; use deepgram::{ speak::flux::options::{Model, Options}, Deepgram, }; #[tokio::main] async fn main() -> Result<(), Box<dyn std::error::Error>> { let api_key = std::env::var("DEEPGRAM_API_KEY")?; let dg = Deepgram::new(&api_key)?; // model is required; encoding defaults to mp3 on the batch transport. let options = Options::builder(Model::FluxHaleyEn).build(); dg.text_to_speech() .flux_speak_to_file("Your appointment is confirmed.", &options, Path::new("flux-tts-batch.mp3")) .await?; Ok(()) } ``` ## Quick start: Flux TTS streaming (WebSocket) ```rust use deepgram::{ speak::flux::{ options::{Encoding, Model, Options}, response::FluxSpeakResponse, }, Deepgram, }; #[tokio::main] async fn main() -> Result<(), Box<dyn std::error::Error>> { let api_key = std::env::var("DEEPGRAM_API_KEY")?; let dg = Deepgram::new(&api_key)?; let options = Options::builder(Model::FluxHaleyEn) .encoding(Encoding::Linear16) .sample_rate(24_000) .build(); // Connect to the /v2/speak WebSocket and get the handle. let speak = dg.text_to_speech(); let mut handle = speak.flux_request(options).handle().await?; // Stream the turn's text in, end the turn with flush, then close. handle.speak("Hello! ").await?; handle.speak("This audio was synthesized over the Flux TTS websocket.").await?; handle.flush().await?; handle.close().await?; // Binary audio frames and JSON control events arrive on receive(). let mut saw_session_metadata = false; while let Some(response) = handle.receive().await { match response? { FluxSpeakResponse::Audio(_bytes) => { /* play or buffer the audio */ } FluxSpeakResponse::SpeechMetadata(_) => { /* end-of-turn signal */ } FluxSpeakResponse::FatalError { code, description, .. } => { return Err(format!("fatal Flux TTS error {code}: {description}").into()); } FluxSpeakResponse::SessionMetadata { .. } => { saw_session_metadata = true; break; } _ => {} } } if !saw_session_metadata { return Err("session ended before its terminal SessionMetadata event".into()); } Ok(()) } ``` `handle.interrupt(playback_offset_ms)` cancels the active turn on barge-in and the server answers with `SpeechInterrupted`; `handle.configure_speed(speed)` changes the speaking rate mid-session and the server answers with `ConfigureSuccess` or `ConfigureFailure`. See `examples/speak/flux/websocket_synthesize.rs` for the full event loop, including saving the audio as a WAV file. ## Key parameters - Entrypoints: `Deepgram::text_to_speech()`, `Speak::speak_to_file(...)`, `Speak::speak_to_stream(...)`, `Speak::speak_stream()`. - TTS `Options` builder fields: `model`, `encoding`, `sample_rate`, `container`, `bit_rate`. - Model enum lives in `deepgram::speak::options::Model` and names the Aura-1 and Aura-2 voices the API served as of this release — `AuraAsteriaEn`, `AuraLunaEn`, `AuraOrionEn`, `Aura2ThaliaEn`, `Aura2AgustinaEs`, `Aura2UzumeJa`, … — plus `CustomId(String)` for anything newer. `Model::from("aura-2-thalia-en")` resolves a wire string to its named variant; a `CustomId` built by hand is not `==` to the named variant it spells, so normalize through `Model::from` before comparing. - Streaming (`speak_stream()`) builder methods: `model`, `encoding`, `sample_rate`, `speed`, `mip_opt_out`, and a `query_params` escape hatch. `handle()` validates locally first: the streaming endpoint accepts only `linear16` / `mulaw` / `alaw`, a `sample_rate` of 8000 / 16000 / 24000 / 32000 / 48000, and `speed` in `0.7..=1.5`; anything else is `DeepgramError::InvalidOptions` before a socket is opened. There is no `container` or `bit_rate` — the stream is raw audio. - `SpeakStreamHandle` (and `SpeakStreamEvents`) implements `futures::Stream<Item = Result<SpeakResponse>>`; `SpeakResponse` is `Audio` / `Metadata` / `Flushed` / `Cleared` / `Warning` / `Unknown`. Sending text never blocks on undrained audio, and sends after the session ends return an error instead of being dropped. - `speak_to_stream(...)` returns `impl Stream<Item = bytes::Bytes>`. - Flux TTS entrypoints: `Speak::flux_speak_to_file(text, &options, path)`, `Speak::flux_speak_to_stream(text, &options)`, `Speak::flux_request(options).handle()` returning `FluxSpeakHandle`. - Flux TTS `Options::builder(Model)` methods: `encoding`, `sample_rate`, `speed`, `expressivity`, `mip_opt_out`, `tag`, and the REST-only `container`, `bit_rate`, `callback`, `callback_method`, `priority_low`. `priority_low()` serializes as `priority=low`. Models are `flux-{voice}-{language}`, for example `Model::FluxHaleyEn`; the WebSocket rejects REST-only options and the compressed encodings (`mp3`, `opus`, `flac`, `aac`) with `DeepgramError::InvalidOptions`. ## API reference (layered) 1. **In-repo** - `README.md` - `src/speak/rest.rs`
View on GitHub
This SKILL.md is very large, so SkillsMP previews the first section here. View on GitHub