> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/argmaxinc/WhisperKit/llms.txt
> Use this file to discover all available pages before exploring further.

# TTSKit

> Main TTS orchestrator class for text-to-speech synthesis

## Overview

`TTSKit` is the main entry point for text-to-speech synthesis. It orchestrates text chunking, concurrent generation, crossfade, and audio playback. The class follows the WhisperKit pattern, exposing each model component as a protocol-typed public property that can be swapped at runtime.

```swift theme={null}
open class TTSKit: @unchecked Sendable
```

## Initialization

### init(\_:)

Create a `TTSKit` instance from a `TTSKitConfig`.

```swift theme={null}
public init(_ config: TTSKitConfig = TTSKitConfig()) async throws
```

<ParamField path="config" type="TTSKitConfig" default="TTSKitConfig()">
  Pipeline configuration containing model variant, paths, compute units, component overrides, and lifecycle flags.
</ParamField>

**Throws:** `TTSError` if the model family is unsupported or component instantiation fails.

**Example:**

```swift theme={null}
let tts = try await TTSKit()
```

### init(model:modelFolder:...)

Convenience initializer that exposes all configuration fields as individual parameters.

```swift theme={null}
public convenience init(
    model: TTSModelVariant = .qwen3TTS_0_6b,
    modelFolder: URL? = nil,
    downloadBase: URL? = nil,
    modelRepo: String = Qwen3TTSConstants.defaultModelRepo,
    tokenizerFolder: URL? = nil,
    modelToken: String? = nil,
    computeOptions: ComputeOptions? = nil,
    textProjector: (any TextProjecting)? = nil,
    codeEmbedder: (any CodeEmbedding)? = nil,
    multiCodeEmbedder: (any MultiCodeEmbedding)? = nil,
    codeDecoder: (any CodeDecoding)? = nil,
    multiCodeDecoder: (any MultiCodeDecoding)? = nil,
    speechDecoder: (any SpeechDecoding)? = nil,
    verbose: Bool = false,
    logLevel: Logging.LogLevel = .debug,
    prewarm: Bool? = nil,
    load: Bool? = nil,
    download: Bool = true,
    useBackgroundDownloadSession: Bool = false,
    seed: UInt64? = nil
) async throws
```

<ParamField path="model" type="TTSModelVariant" default=".qwen3TTS_0_6b">
  Model variant to use.
</ParamField>

<ParamField path="modelFolder" type="URL?" default="nil">
  Explicit local folder URL. When provided, download is skipped.
</ParamField>

<ParamField path="downloadBase" type="URL?" default="nil">
  Base URL for Hub cache.
</ParamField>

<ParamField path="modelRepo" type="String" default="Qwen3TTSConstants.defaultModelRepo">
  HuggingFace repo ID.
</ParamField>

<ParamField path="tokenizerFolder" type="URL?" default="nil">
  Local tokenizer folder path.
</ParamField>

<ParamField path="modelToken" type="String?" default="nil">
  HuggingFace API token.
</ParamField>

<ParamField path="computeOptions" type="ComputeOptions?" default="nil">
  Per-component CoreML compute unit configuration.
</ParamField>

<ParamField path="textProjector" type="(any TextProjecting)?" default="nil">
  Custom text projector implementation.
</ParamField>

<ParamField path="codeEmbedder" type="(any CodeEmbedding)?" default="nil">
  Custom code embedder implementation.
</ParamField>

<ParamField path="multiCodeEmbedder" type="(any MultiCodeEmbedding)?" default="nil">
  Custom multi-code embedder implementation.
</ParamField>

<ParamField path="codeDecoder" type="(any CodeDecoding)?" default="nil">
  Custom code decoder implementation.
</ParamField>

<ParamField path="multiCodeDecoder" type="(any MultiCodeDecoding)?" default="nil">
  Custom multi-code decoder implementation.
</ParamField>

<ParamField path="speechDecoder" type="(any SpeechDecoding)?" default="nil">
  Custom speech decoder implementation.
</ParamField>

<ParamField path="verbose" type="Bool" default="false">
  Enable diagnostic logging.
</ParamField>

<ParamField path="logLevel" type="Logging.LogLevel" default=".debug">
  Logging level when verbose is true.
</ParamField>

<ParamField path="prewarm" type="Bool?" default="nil">
  Enable model prewarming to serialize compilation.
</ParamField>

<ParamField path="load" type="Bool?" default="nil">
  Load models immediately after init. `nil` loads when modelFolder is non-nil.
</ParamField>

<ParamField path="download" type="Bool" default="true">
  Download models if not already available locally.
</ParamField>

<ParamField path="useBackgroundDownloadSession" type="Bool" default="false">
  Use a background URLSession for model downloads.
</ParamField>

<ParamField path="seed" type="UInt64?" default="nil">
  Optional seed for reproducible generation.
</ParamField>

## Properties

### Model Components

<ResponseField name="textProjector" type="any TextProjecting">
  Text token to embedding converter. Swappable at runtime.
</ResponseField>

<ResponseField name="codeEmbedder" type="any CodeEmbedding">
  Codec-0 token to embedding converter.
</ResponseField>

<ResponseField name="multiCodeEmbedder" type="any MultiCodeEmbedding">
  Multi-code token to embedding converter.
</ResponseField>

<ResponseField name="codeDecoder" type="any CodeDecoding">
  Autoregressive code-0 decoder.
</ResponseField>

<ResponseField name="multiCodeDecoder" type="any MultiCodeDecoding">
  Per-frame decoder.
</ResponseField>

<ResponseField name="speechDecoder" type="any SpeechDecoding">
  RVQ codes to audio waveform converter.
</ResponseField>

<ResponseField name="tokenizer" type="(any Tokenizer)?">
  Tokenizer instance. `nil` before the first `loadModels()` call or after `unloadModels()`.
</ResponseField>

### State

<ResponseField name="modelState" type="ModelState">
  Current lifecycle state of the loaded models. Read-only.

  Transitions: `.unloaded` → `.downloading` → `.downloaded` → `.loading` → `.loaded`

  Or: `.unloaded` → `.prewarming` → `.prewarmed`
</ResponseField>

<ResponseField name="config" type="TTSKitConfig">
  Pipeline configuration.
</ResponseField>

<ResponseField name="modelFolder" type="URL?">
  Direct accessor for the resolved local model folder. Backed by `config.modelFolder`.
</ResponseField>

<ResponseField name="useBackgroundDownloadSession" type="Bool">
  Whether to use a background URLSession for model downloads. Backed by `config.useBackgroundDownloadSession`.
</ResponseField>

<ResponseField name="currentTimings" type="SpeechTimings">
  Cumulative timings for the most recent pipeline run. Read-only.
</ResponseField>

<ResponseField name="modelLoadTime" type="TimeInterval">
  Wall-clock seconds for the most recent full model load. Read-only.
</ResponseField>

<ResponseField name="tokenizerLoadTime" type="TimeInterval">
  Wall-clock seconds for the most recent tokenizer load. Read-only.
</ResponseField>

<ResponseField name="audioOutput" type="AudioOutput">
  Audio output instance used by `play()`. Read-only.
</ResponseField>

<ResponseField name="promptCache" type="TTSPromptCache?">
  Cached prefix state for the most recently used voice/language/instruction.
  Automatically built on the first `generate` call and reused for subsequent calls with the same parameters.
  Set to `nil` to force a full prefill.
</ResponseField>

<ResponseField name="modelStateCallback" type="ModelStateCallback?">
  Invoked whenever `modelState` changes.
</ResponseField>

<ResponseField name="seed" type="UInt64?">
  Seed for reproducible generation. Read-only.
</ResponseField>

## Static Methods

### recommendedModels()

Returns the recommended model variant for the current platform.

```swift theme={null}
public static func recommendedModels() -> TTSModelVariant
```

<ResponseField name="returns" type="TTSModelVariant">
  The best default variant for the current platform.
</ResponseField>

### fetchAvailableModels(from:matching:downloadBase:token:endpoint:)

Fetch all available model variants from the HuggingFace Hub.

```swift theme={null}
public static func fetchAvailableModels(
    from repo: String = Qwen3TTSConstants.defaultModelRepo,
    matching: [String] = ["*"],
    downloadBase: URL? = nil,
    token: String? = nil,
    endpoint: String = Qwen3TTSConstants.defaultEndpoint
) async throws -> [String]
```

<ParamField path="repo" type="String" default="Qwen3TTSConstants.defaultModelRepo">
  HuggingFace repo ID to query.
</ParamField>

<ParamField path="matching" type="[String]" default="[&#x22;*&#x22;]">
  Glob patterns to filter returned variant names.
</ParamField>

<ParamField path="downloadBase" type="URL?" default="nil">
  Optional base URL for Hub downloads.
</ParamField>

<ParamField path="token" type="String?" default="nil">
  HuggingFace API token.
</ParamField>

<ParamField path="endpoint" type="String" default="Qwen3TTSConstants.defaultEndpoint">
  HuggingFace Hub endpoint URL.
</ParamField>

<ResponseField name="returns" type="[String]">
  Display names of available model variants matching the given patterns.
</ResponseField>

**Throws:** `TTSError` if the Hub request fails.

### download(variant:downloadBase:useBackgroundSession:from:token:endpoint:revision:additionalPatterns:progressCallback:)

Download models for a specific variant from HuggingFace Hub.

```swift theme={null}
open class func download(
    variant: TTSModelVariant = .defaultForCurrentPlatform,
    downloadBase: URL? = nil,
    useBackgroundSession: Bool = false,
    from repo: String = Qwen3TTSConstants.defaultModelRepo,
    token: String? = nil,
    endpoint: String = Qwen3TTSConstants.defaultEndpoint,
    revision: String? = nil,
    additionalPatterns: [String] = [],
    progressCallback: (@Sendable (Progress) -> Void)? = nil
) async throws -> URL
```

<ParamField path="variant" type="TTSModelVariant" default=".defaultForCurrentPlatform">
  The model variant to download.
</ParamField>

<ParamField path="downloadBase" type="URL?" default="nil">
  Base URL for the local cache.
</ParamField>

<ParamField path="useBackgroundSession" type="Bool" default="false">
  Use a background URLSession for the download.
</ParamField>

<ParamField path="repo" type="String" default="Qwen3TTSConstants.defaultModelRepo">
  HuggingFace repo ID.
</ParamField>

<ParamField path="token" type="String?" default="nil">
  HuggingFace API token.
</ParamField>

<ParamField path="endpoint" type="String" default="Qwen3TTSConstants.defaultEndpoint">
  HuggingFace Hub endpoint URL.
</ParamField>

<ParamField path="revision" type="String?" default="nil">
  Specific git revision (commit SHA, tag, or branch) to download.
</ParamField>

<ParamField path="additionalPatterns" type="[String]" default="[]">
  Extra glob patterns to include alongside the default component patterns.
</ParamField>

<ParamField path="progressCallback" type="(@Sendable (Progress) -> Void)?" default="nil">
  Optional closure receiving download progress updates.
</ParamField>

<ResponseField name="returns" type="URL">
  Local URL of the downloaded model folder.
</ResponseField>

**Throws:** `TTSError` if the Hub download fails.

### download(config:progressCallback:)

Download models using a full `TTSKitConfig`.

```swift theme={null}
open class func download(
    config: TTSKitConfig = TTSKitConfig(),
    progressCallback: (@Sendable (Progress) -> Void)? = nil
) async throws -> URL
```

<ParamField path="config" type="TTSKitConfig" default="TTSKitConfig()">
  Pipeline configuration containing `modelRepo`, `modelToken`, `downloadRevision`, `downloadAdditionalPatterns`, and variant settings.
</ParamField>

<ParamField path="progressCallback" type="(@Sendable (Progress) -> Void)?" default="nil">
  Optional closure receiving download progress updates.
</ParamField>

<ResponseField name="returns" type="URL">
  Local URL of the downloaded model folder.
</ResponseField>

**Throws:** `TTSError` if the Hub download fails.

## Instance Methods

### Model Lifecycle

#### setupModels(model:downloadBase:modelRepo:modelToken:modelFolder:download:endpoint:)

Resolve the local model folder, downloading from HuggingFace Hub if needed.

```swift theme={null}
open func setupModels(
    model: TTSModelVariant? = nil,
    downloadBase: URL? = nil,
    modelRepo: String? = nil,
    modelToken: String? = nil,
    modelFolder: URL? = nil,
    download: Bool,
    endpoint: String = Qwen3TTSConstants.defaultEndpoint
) async throws
```

<ParamField path="model" type="TTSModelVariant?" default="nil">
  Model variant to download. `nil` uses `config.model`.
</ParamField>

<ParamField path="downloadBase" type="URL?" default="nil">
  Base URL for Hub cache. `nil` uses the Hub library default.
</ParamField>

<ParamField path="modelRepo" type="String?" default="nil">
  HuggingFace repo ID. `nil` uses `config.modelRepo`.
</ParamField>

<ParamField path="modelToken" type="String?" default="nil">
  HuggingFace API token. `nil` uses `config.modelToken`.
</ParamField>

<ParamField path="modelFolder" type="URL?" default="nil">
  Explicit local folder URL. When non-nil the download is skipped.
</ParamField>

<ParamField path="download" type="Bool" required>
  When `true` and `modelFolder` is nil, download from the resolved repo.
</ParamField>

<ParamField path="endpoint" type="String" default="Qwen3TTSConstants.defaultEndpoint">
  HuggingFace Hub endpoint URL.
</ParamField>

**Throws:** `TTSError` if the download fails or the model folder cannot be resolved.

#### prewarmModels()

Prewarm all CoreML models by compiling them sequentially, then discarding weights.

```swift theme={null}
open func prewarmModels() async throws
```

Serializes CoreML compilation to cap peak memory. Call before `loadModels()` on first launch or after a model update.

**Throws:** `TTSError` if model compilation fails.

#### loadModels(prewarmMode:)

Load all models and the tokenizer.

```swift theme={null}
open func loadModels(prewarmMode: Bool = false) async throws
```

<ParamField path="prewarmMode" type="Bool" default="false">
  When `true`, compile models one at a time and discard weights to limit peak memory (prewarm).
  When `false` (default), load all concurrently.
</ParamField>

Expects `config.modelFolder` to be set (call `setupModels` first if needed).

**Throws:** `TTSError` if model compilation or tokenizer loading fails.

#### loadTokenizerIfNeeded()

Load the tokenizer only if it has not been loaded yet.

```swift theme={null}
open func loadTokenizerIfNeeded() async throws
```

Skips loading when `tokenizer` is already set.

**Throws:** `TTSError` if tokenizer loading fails.

#### loadTokenizer()

Load the tokenizer from `config.tokenizerSource`.

```swift theme={null}
open func loadTokenizer() async throws -> any Tokenizer
```

Checks for a local `tokenizer.json` file first; falls back to downloading from the Hugging Face Hub if no local file is found.

<ResponseField name="returns" type="any Tokenizer">
  The loaded tokenizer instance.
</ResponseField>

**Throws:** `TTSError` if tokenizer loading fails.

#### unloadModels()

Release all model weights and the tokenizer from memory.

```swift theme={null}
open func unloadModels() async
```

Transitions through `.unloading` before reaching `.unloaded`.

#### clearState()

Reset all accumulated timing statistics.

```swift theme={null}
open func clearState()
```

Call between generation runs when you want fresh per-run timing data.

### Pipeline Setup

#### setupPipeline(for:config:)

Configure the model-specific component properties for the active model family.

```swift theme={null}
open func setupPipeline(for variant: TTSModelVariant, config: TTSKitConfig)
```

<ParamField path="variant" type="TTSModelVariant" required>
  Model variant to configure.
</ParamField>

<ParamField path="config" type="TTSKitConfig" required>
  Configuration containing component overrides.
</ParamField>

Uses the component overrides in `config` if set; otherwise instantiates the default components for the given variant's model family.

#### setupGenerateTask(currentTimings:progress:tokenizer:sampler:)

Setup the generate task used for speech synthesis.

```swift theme={null}
open func setupGenerateTask(
    currentTimings: SpeechTimings,
    progress: Progress,
    tokenizer: any Tokenizer,
    sampler: any TokenSampling
) throws -> any SpeechGenerating
```

<ParamField path="currentTimings" type="SpeechTimings" required>
  Timing accumulator for the current run.
</ParamField>

<ParamField path="progress" type="Progress" required>
  Progress tracking instance.
</ParamField>

<ParamField path="tokenizer" type="any Tokenizer" required>
  Tokenizer instance.
</ParamField>

<ParamField path="sampler" type="any TokenSampling" required>
  Token sampling strategy.
</ParamField>

<ResponseField name="returns" type="any SpeechGenerating">
  A configured generation task.
</ResponseField>

Subclasses may override to provide custom behavior.

**Throws:** `TTSError` if task setup fails.

#### createTask(progress:)

Create a fresh generation task with the guard/seed/counter boilerplate.

```swift theme={null}
open func createTask(progress: Progress? = nil) throws -> any SpeechGenerating
```

<ParamField path="progress" type="Progress?" default="nil">
  Optional progress tracking instance.
</ParamField>

<ResponseField name="returns" type="any SpeechGenerating">
  An independent task with its own sampler seed and per-task buffers.
</ResponseField>

**Throws:** `TTSError` if the tokenizer is not loaded.

### Speech Generation

#### generate(text:voice:language:options:callback:)

Synthesize speech from text and return the complete audio result.

```swift theme={null}
open func generate(
    text: String,
    voice: String? = nil,
    language: String? = nil,
    options: GenerationOptions = GenerationOptions(),
    callback: SpeechCallback = nil
) async throws -> SpeechResult
```

<ParamField path="text" type="String" required>
  The text to synthesize.
</ParamField>

<ParamField path="voice" type="String?" default="nil">
  Voice/speaker identifier. Format is model-specific (e.g., `"ryan"` for Qwen3 TTS).
</ParamField>

<ParamField path="language" type="String?" default="nil">
  Language identifier. Format is model-specific (e.g., `"english"` for Qwen3 TTS).
</ParamField>

<ParamField path="options" type="GenerationOptions" default="GenerationOptions()">
  Sampling and generation options.
</ParamField>

<ParamField path="callback" type="SpeechCallback" default="nil">
  Optional per-step callback receiving decoded audio chunks. Return `false` to cancel; `nil` or `true` to continue.
</ParamField>

<ResponseField name="returns" type="SpeechResult">
  A `SpeechResult` containing the raw audio samples and timing breakdown.
</ResponseField>

Handles text chunking, optional prompt caching, and concurrent multi-chunk generation.

**Throws:** `TTSError` if text is empty, models are not loaded, or generation fails.

#### generate(text:speaker:language:options:callback:)

Generate speech from text using typed Qwen3 speaker and language enums.

```swift theme={null}
open func generate(
    text: String,
    speaker: Qwen3Speaker,
    language: Qwen3Language = .english,
    options: GenerationOptions = GenerationOptions(),
    callback: SpeechCallback = nil
) async throws -> SpeechResult
```

<ParamField path="text" type="String" required>
  Input text to synthesise.
</ParamField>

<ParamField path="speaker" type="Qwen3Speaker" required>
  The `Qwen3Speaker` voice to use.
</ParamField>

<ParamField path="language" type="Qwen3Language" default=".english">
  The `Qwen3Language` to synthesise in.
</ParamField>

<ParamField path="options" type="GenerationOptions" default="GenerationOptions()">
  Generation options controlling sampling, chunking, and concurrency.
</ParamField>

<ParamField path="callback" type="SpeechCallback" default="nil">
  Per-step callback receiving decoded audio chunks. Return `false` to cancel.
</ParamField>

<ResponseField name="returns" type="SpeechResult">
  The assembled `SpeechResult`.
</ResponseField>

**Throws:** `TTSError` on generation failure or task cancellation.

#### play(text:voice:language:options:playbackStrategy:callback:)

Generate speech and stream it through the audio output in real time.

```swift theme={null}
open func play(
    text: String,
    voice: String? = nil,
    language: String? = nil,
    options: GenerationOptions = GenerationOptions(),
    playbackStrategy: PlaybackStrategy = .auto,
    callback: SpeechCallback = nil
) async throws -> SpeechResult
```

<ParamField path="text" type="String" required>
  The text to synthesize.
</ParamField>

<ParamField path="voice" type="String?" default="nil">
  Voice/speaker identifier.
</ParamField>

<ParamField path="language" type="String?" default="nil">
  Language identifier.
</ParamField>

<ParamField path="options" type="GenerationOptions" default="GenerationOptions()">
  Sampling and generation options.
</ParamField>

<ParamField path="playbackStrategy" type="PlaybackStrategy" default=".auto">
  Controls how audio is buffered before playback begins.
</ParamField>

<ParamField path="callback" type="SpeechCallback" default="nil">
  Optional per-step callback.
</ParamField>

<ResponseField name="returns" type="SpeechResult">
  A `SpeechResult` with the complete audio and timing breakdown.
</ResponseField>

For streaming strategies (auto, stream, buffered) chunking is forced to sequential (`concurrentWorkerCount = 1`) so frames can be enqueued in order.

**Throws:** `TTSError` on generation failure or task cancellation.

#### play(text:speaker:language:options:playbackStrategy:callback:)

Generate speech and stream playback using typed Qwen3 speaker and language enums.

```swift theme={null}
open func play(
    text: String,
    speaker: Qwen3Speaker,
    language: Qwen3Language = .english,
    options: GenerationOptions = GenerationOptions(),
    playbackStrategy: PlaybackStrategy = .auto,
    callback: SpeechCallback = nil
) async throws -> SpeechResult
```

<ParamField path="text" type="String" required>
  Input text to synthesise.
</ParamField>

<ParamField path="speaker" type="Qwen3Speaker" required>
  The `Qwen3Speaker` voice to use.
</ParamField>

<ParamField path="language" type="Qwen3Language" default=".english">
  The `Qwen3Language` to synthesise in.
</ParamField>

<ParamField path="options" type="GenerationOptions" default="GenerationOptions()">
  Generation options controlling sampling, chunking, and concurrency.
</ParamField>

<ParamField path="playbackStrategy" type="PlaybackStrategy" default=".auto">
  Controls how much audio is buffered before playback begins.
</ParamField>

<ParamField path="callback" type="SpeechCallback" default="nil">
  Per-step callback receiving decoded audio chunks. Return `false` to cancel.
</ParamField>

<ResponseField name="returns" type="SpeechResult">
  The assembled `SpeechResult`.
</ResponseField>

**Throws:** `TTSError` on generation failure or task cancellation.

### Prompt Cache Management

#### buildPromptCache(voice:language:instruction:)

Build a prompt cache for the given voice/language/instruction combination.

```swift theme={null}
open func buildPromptCache(
    voice: String? = nil,
    language: String? = nil,
    instruction: String? = nil
) async throws -> TTSPromptCache
```

<ParamField path="voice" type="String?" default="nil">
  Voice/speaker identifier. `nil` uses the model's `defaultVoice`.
</ParamField>

<ParamField path="language" type="String?" default="nil">
  Language identifier. `nil` uses the model's `defaultLanguage`.
</ParamField>

<ParamField path="instruction" type="String?" default="nil">
  Optional style instruction prepended to the TTS prompt.
</ParamField>

<ResponseField name="returns" type="TTSPromptCache">
  The built `TTSPromptCache` that can be passed to subsequent `generate` calls.
</ResponseField>

Pre-computes the invariant prefix embeddings and prefills them through the CodeDecoder, returning a reusable cache that eliminates \~90% of prefill cost on subsequent `generate` calls.

**Throws:** `TTSError` if the model is not loaded or prompt caching is unsupported.

#### buildPromptCache(speaker:language:instruction:)

Build a prompt cache using typed Qwen3 speaker and language enums.

```swift theme={null}
open func buildPromptCache(
    speaker: Qwen3Speaker,
    language: Qwen3Language,
    instruction: String? = nil
) async throws -> TTSPromptCache
```

<ParamField path="speaker" type="Qwen3Speaker" required>
  The `Qwen3Speaker` to pre-warm the cache for.
</ParamField>

<ParamField path="language" type="Qwen3Language" required>
  The `Qwen3Language` to pre-warm the cache for.
</ParamField>

<ParamField path="instruction" type="String?" default="nil">
  Optional style instruction (1.7B only).
</ParamField>

<ResponseField name="returns" type="TTSPromptCache">
  A `TTSPromptCache` for the given parameters.
</ResponseField>

**Throws:** `TTSError` on generation failure.

#### savePromptCache()

Save the current prompt cache to disk under the model's embeddings directory.

```swift theme={null}
public func savePromptCache() throws
```

The file is saved at `<modelFolder>/embeddings/<voice>_<language>.promptcache`.

**Throws:** `TTSError` if saving fails or modelFolder is not set.

#### loadPromptCache(voice:language:instruction:)

Load a prompt cache from disk if one exists for the given parameters.

```swift theme={null}
public func loadPromptCache(
    voice: String,
    language: String,
    instruction: String? = nil
) -> TTSPromptCache?
```

<ParamField path="voice" type="String" required>
  Voice/speaker identifier.
</ParamField>

<ParamField path="language" type="String" required>
  Language identifier.
</ParamField>

<ParamField path="instruction" type="String?" default="nil">
  Optional style instruction.
</ParamField>

<ResponseField name="returns" type="TTSPromptCache?">
  The loaded cache, or `nil` if not found.
</ResponseField>

Returns `nil` if no cached file exists. Also stores the loaded cache on `self.promptCache` for automatic reuse.

### Logging

#### loggingCallback(\_:)

Register a custom log sink for all `Logging` output from TTSKit.

```swift theme={null}
open func loggingCallback(_ callback: Logging.LoggingCallback?)
```

<ParamField path="callback" type="Logging.LoggingCallback?" required>
  Custom logging callback. Pass `nil` to restore the default print-based logger.
</ParamField>

## SpeechModel Conformance

<ResponseField name="sampleRate" type="Int">
  The output sample rate of the currently loaded speech decoder.
</ResponseField>

## Example Usage

### Basic Generation

```swift theme={null}
let tts = try await TTSKit()
let result = try await tts.generate(
    text: "Hello, world!",
    voice: "ryan",
    language: "english"
)
print("Generated \(result.audio.count) samples")
```

### With Custom Configuration

```swift theme={null}
var config = TTSKitConfig(
    model: .qwen3TTS_0_6b,
    verbose: true,
    seed: 42
)
let tts = try await TTSKit(config)
```

### Real-time Playback

```swift theme={null}
let result = try await tts.play(
    text: "This is streaming audio.",
    speaker: .ryan,
    playbackStrategy: .auto
)
```

### Component Swapping

```swift theme={null}
let config = TTSKitConfig(load: false)
let tts = try await TTSKit(config)
tts.codeDecoder = MyOptimizedCodeDecoder()
try await tts.loadModels()
```
