Skip to main content

Goal

Stock phrases (greetings, hold messages, sign-offs) repeat across calls. Regenerating them every time adds latency and costs credits. Instead, pre-generate those phrases once as raw PCM, cache them, and splice them into a live TTS stream at runtime. Cached clips skip the API, so those segments are faster and free.

Before you start

You need:
  • API key — Get your API key from play.cartesia.ai. If you’re new to Cartesia, see the Realtime TTS Quickstart.
  • Raw container — Set container: "raw" (headerless PCM). Containers like WAV or MP3 add headers that break concatenation. See TTS Output Format.
  • Matching encoding and sample rate — Cached clips must match your live stream exactly (e.g., pcm_s16le at 24000 Hz).
  • Matching model, voice, and language — Pin a dated model snapshot in production (e.g., sonic-3.5-2026-05-04) so cached and live audio sound identical.
Cached and live audio must be byte-compatible so they concatenate without clicks or distortion.

Project setup

To follow along with this guide, initialize a python uv project called tts-caching as follows:

Step 1: Build the phrase cache

Generate the audio phrase cache with the below script. It generates each phrase in PHRASES and saves the raw audio PCM bytes in a phrase-cache directory.
build_cache.py
Run once:

Step 2: Interleave at runtime

At runtime, process a sequence of cached and live phrases into one output buffer.
interleave_tts.py
Run it:
Listen to spliced.wav. The cached phrases blend seamlessly with the live-generated audio.

Design pattern

In interleave_tts.py the WebSocket stays open for the whole sequence. Only “live” phrases call Cartesia TTS. Cached phrases come from your store (disk, S3, anywhere), so you pay credits only for the live parts.

Important things to note

  • Audio Format mismatch: If cached clips use a different encoding or sample rate than live audio, you’ll hear clicks or distortion at the joins.
  • Pin your model: Using different TTS model versions can affect the voice generation even if it’s the same voice ID. Pin a dated snapshot (eg sonic-3.5-2026-05-04) so cached and live audio stay in sync.
  • 5-minute idle timeout: TTS WebSockets close after 5 minutes of inactivity. Don’t disconnect just to play a cached clip; that only adds reconnect cost. If you have long gaps between live generations, close and reopen rather than holding the connection idle.
  • Full phrases splice cleanly: Sonic TTS uses surrounding words as context for emotiveness and tone. Aim to make your TTS clips start and end as a complete sentence.
  • WebSocket pattern: This guide uses TTS WebSocket, which keeps one connection open across multiple generations. The Bytes and SSE endpoints work one request per generation, so there is no open connection to interleave with. See TTS endpoint types.