# How FluidAudio Handles Model Downloads and Caching

> Discover how FluidAudio manages model downloads and caching with its centralized subsystem. Learn how it fetches, caches, and verifies Core ML models for efficient use.

- Repository: [Fluid Inference/fluidaudio](https://github.com/fluidinference/fluidaudio)
- Tags: internals
- Published: 2026-03-02

---

**FluidAudio uses a centralized download subsystem to pull pre-trained Core ML models from Hugging Face (or custom registries), cache them in platform-specific directories, and verify integrity before loading them into `MLModel` instances.**

FluidAudio, the open-source speech processing framework from fluidinference, relies on a robust model management layer to deliver Core ML assets efficiently. Understanding how FluidAudio handles model downloads and caching is essential for deploying offline-capable applications, optimizing network usage, and troubleshooting deployment issues.

## Registry Configuration

`ModelRegistry` provides a **single point of truth** for constructing URLs and configuring the HTTP session used throughout the download pipeline.

The *base URL* can be overridden programmatically, via the `REGISTRY_URL` or `MODEL_REGISTRY_URL` environment variables, or defaults to `https://huggingface.co`【/Sources/FluidAudio/ModelRegistry.swift#L30-L38】. Proxy settings are read from `http_proxy` / `https_proxy` (macOS only) and added to the `URLSessionConfiguration` through `configureProxySettings()`【/Sources/FluidAudio/ModelRegistry.swift#L94-L126】.

A shared `URLSession` is exposed through `DownloadUtils.sharedSession` so every downloader re-uses the same configuration【/Sources/FluidAudio/DownloadUtils.swift#L10-L12】.

```swift
// Example: Override the registry URL at runtime
ModelRegistry.baseURL = "https://my-mirror.example.com"

```

## Cache Layout and Storage Locations

FluidAudio uses **platform-specific directories** to store downloaded assets, with different model types cached in distinct locations to avoid conflicts.

### TTS Models (Kokoro / PocketTTS)

These are cached under `~/.cache/fluidaudio/Models/` on macOS and Linux, or the platform-specific caches directory on iOS. The `TtsModels.getCacheDirectory()` method creates `~/.cache/fluidaudio` if missing and returns the path【/Sources/FluidAudioEspeak/TextToSpeech/TtsModels.swift#L86-L102】.

### ASR, VAD, and Diarization Models

These are stored in the *Application Support* folder: `~/Library/Application Support/FluidAudio/Models/` on macOS【/Sources/FluidAudio/DownloadUtils.swift#L13-L19】.

Both locations are created **lazily** the first time a model is downloaded.

## The Download Flow

The download process follows a **cache-first** strategy that minimizes network traffic and ensures atomic updates.

### High-Level Entry Points

For **TTS models**, `TtsModels.download(variants:from:directory:)` builds the target directory, resolves the list of model file names, and calls `DownloadUtils.loadModels`【/Sources/FluidAudioEspeak/TextToSpeech/TtsModels.swift#L27-L48】.

For **ASR, VAD, and Diarizer** components, each invokes `DownloadUtils.loadModels(repo:modelNames:directory:computeUnits:)` directly (e.g., `ASRModels.load(...)` inside the ASR module).

### Cache-First Verification

`loadModelsOnce` (called by `loadModels`) first creates the destination folder, then checks whether **all required model files** already exist【/Sources/FluidAudio/DownloadUtils.swift#L44-L50】. If they do, no network traffic occurs and the cached models are loaded immediately.

### Repository Enumeration

If cache validation fails, `downloadRepo` walks the remote repository using the Hugging Face **tree API** (`/api/models/.../tree/main/...`). It builds a list of files that match the required patterns (model folders, metadata, binary blobs)【/Sources/FluidAudio/DownloadUtils.swift#L33-L88】.

### Streaming and Error Handling

For each entry, a `URLRequest` is created with optional `Authorization: Bearer <HF_TOKEN>` header via `DownloadUtils.authorizedRequest`【/Sources/FluidAudio/DownloadUtils.swift#L24-L33】. The request is handed to `sharedSession.download(for:)`, which writes a temporary file and then moves it to the final location【/Sources/FluidAudio/DownloadUtils.swift#L30-L55】.

- **Zero-byte files** are handled specially (created locally) because Hugging Face returns a 500 error for them【/Sources/FluidAudio/DownloadUtils.swift#L20-L24】.
- **Rate-limit** (`429` / `503`) and generic HTTP errors are wrapped into `HuggingFaceDownloadError` and surfaced to the caller【/Sources/FluidAudio/DownloadUtils.swift#L42-L48】.

### Model Instantiation

After download, each model directory is verified to contain `coremldata.bin`. The model is then instantiated with a **custom `MLModelConfiguration`** that selects the appropriate compute units (`.cpuAndNeuralEngine` for TTS, `.cpuAndGPU` for Kokoro)【/Sources/FluidAudio/DownloadUtils.swift#L58-L62】.

```swift
let config = MLModelConfiguration()
config.computeUnits = .cpuAndNeuralEngine
let model = try MLModel(contentsOf: modelPath, configuration: config)

```

## Cache Management Utilities

FluidAudio provides utilities to manage disk space used by cached models.

- **Clear a single repository** – `DownloadUtils.clearModelCache(forRepo:directory:)`.
- **Clear all caches** – `DownloadUtils.clearAllModelCaches()` removes both the Application Support and the `~/.cache/fluidaudio` trees【/Sources/FluidAudio/DownloadUtils.swift#L100-L131】.

These utilities are used by the CLI (`fluidaudio clear-cache`) and in integration tests.

## Practical Code Examples

### Downloading TTS Models (Kokoro)

```swift
import FluidAudioEspeak

let variants: Set<ModelNames.TTS.Variant> = [.fiveSecond, .fifteenSecond]

// Download (or reuse cached) models into the default cache directory
let ttsModels = try await TtsModels.download(
    variants: variants,
    progressHandler: { progress in
        print("Download progress: \(Int(progress * 100))%")
    }
)

// Access a specific model for synthesis
if let model = ttsModels.model(for: .fiveSecond) {
    // Use `model` with the KokoroSynthesizer
}

```

*The method internally calls `DownloadUtils.loadModels` and stores files under `~/.cache/fluidaudio/Models/kokoro/`.*

### Loading an ASR Model Directly

```swift
import FluidAudio

let repo = Repo.asr // defined in ModelNames.swift
let modelNames = ["asr_coreml.model"]   // names required for the selected repo

let models = try await DownloadUtils.loadModels(
    repo,
    modelNames: modelNames,
    directory: try ModelRegistry.configuredCacheDirectory(),
    computeUnits: .cpuAndGPU
)

let asrModel = models["asr_coreml.model"]!

```

### Configuring Proxies and Custom Registries

```swift
// Use a corporate mirror and an HTTP proxy
ModelRegistry.baseURL = "https://my-mirror.company.com"
setenv("http_proxy", "http://proxy.company.com:3128", 1)

// Subsequent downloads will respect these settings automatically
let _ = try await TtsModels.download()

```

### Clearing the Model Cache

```swift
import FluidAudio

DownloadUtils.clearAllModelCaches()
print("All downloaded models have been removed.")

```

## Summary

- **FluidAudio** manages Core ML models through a centralized registry system that defaults to Hugging Face but supports custom mirrors via `ModelRegistry.baseURL`.
- **Cache-first architecture** ensures that `DownloadUtils.loadModels` checks local storage in `~/.cache/fluidaudio/` (TTS) or `~/Library/Application Support/FluidAudio/` (ASR/VAD) before initiating network requests.
- **Robust download pipeline** handles zero-byte files, rate limiting, and authentication tokens, streaming files via a shared `URLSession` configured for proxy support.
- **Automatic model instantiation** validates downloaded `coremldata.bin` files and configures compute units (CPU/GPU/Neural Engine) appropriate for each model type.

## Frequently Asked Questions

### Can FluidAudio work completely offline?

Yes, once models are cached, FluidAudio operates entirely offline. The `loadModels` method performs a cache-first check【/Sources/FluidAudio/DownloadUtils.swift#L44-L50】; if all required files exist locally, no network connection is established. Ensure you download models during the initial setup while connected to the internet.

### How do I use a private Hugging Face model repository?

Set the `HF_TOKEN` environment variable or configure the authorization header in your application. The `DownloadUtils.authorizedRequest` method automatically injects `Authorization: Bearer <HF_TOKEN>` into download requests【/Sources/FluidAudio/DownloadUtils.swift#L24-L33】. Additionally, override `ModelRegistry.baseURL` if using a private registry mirror.

### Where exactly are models stored on macOS?

TTS models (Kokoro, PocketTTS) reside in `~/.cache/fluidaudio/Models/`, while ASR, VAD, and diarization models are stored in `~/Library/Application Support/FluidAudio/Models/`【/Sources/FluidAudioEspeak/TextToSpeech/TtsModels.swift#L86-L102】【/Sources/FluidAudio/DownloadUtils.swift#L13-L19】. Both paths are created lazily on first download.

### What happens if a download is interrupted?

FluidAudio streams files to temporary locations before atomic moves to the final cache path【/Sources/FluidAudio/DownloadUtils.swift#L30-L55】. If a download is interrupted, the temporary file is discarded, and the next request will restart the download for that specific file. The cache-first check ensures partial downloads do not satisfy future requests; only complete, verified files are used.