> ## 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.

# ModelState

> Lifecycle state of a loaded ML model pipeline

`ModelState` is an enum that represents the current lifecycle state of a WhisperKit or TTSKit model pipeline.

## Overview

Model loading and management involves several distinct states. `ModelState` provides a single canonical type that can be referenced across UI components, callbacks, and utilities to track where a model is in its lifecycle.

## Cases

<ResponseField name="unloading" type="ModelState">
  The model is currently being unloaded from memory.

  **Description**: "Unloading"
</ResponseField>

<ResponseField name="unloaded" type="ModelState">
  The model is not loaded in memory.

  **Description**: "Unloaded"
</ResponseField>

<ResponseField name="loading" type="ModelState">
  The model is currently being loaded into memory.

  **Description**: "Loading"
</ResponseField>

<ResponseField name="loaded" type="ModelState">
  The model is fully loaded and ready for use.

  **Description**: "Loaded"
</ResponseField>

<ResponseField name="prewarming" type="ModelState">
  The model is being specialized for the device (one-time compilation).

  **Description**: "Specializing"
</ResponseField>

<ResponseField name="prewarmed" type="ModelState">
  The model has been specialized and cached.

  **Description**: "Specialized"
</ResponseField>

<ResponseField name="downloading" type="ModelState">
  The model files are being downloaded.

  **Description**: "Downloading"
</ResponseField>

<ResponseField name="downloaded" type="ModelState">
  The model files have been downloaded.

  **Description**: "Downloaded"
</ResponseField>

## Properties

<ResponseField name="description" type="String">
  A human-readable description of the current state.

  ```swift theme={null}
  let state = ModelState.loading
  print(state.description) // "Loading"
  ```
</ResponseField>

<ResponseField name="isBusy" type="Bool">
  Returns `true` when a loading, unloading, downloading, or prewarming operation is in progress.

  ```swift theme={null}
  let state = ModelState.loading
  if state.isBusy {
      // Show loading indicator
  }
  ```

  Returns `true` for: `.loading`, `.prewarming`, `.downloading`, `.unloading`

  Returns `false` for: `.unloaded`, `.loaded`, `.prewarmed`, `.downloaded`
</ResponseField>

## State Machine

The typical state transitions follow these patterns:

```
unloaded → downloading → downloaded → loading → loaded
unloaded → prewarming → prewarmed
loaded   → unloading  → unloaded
```

### Download and Load Flow

When a model needs to be downloaded and loaded:

1. `unloaded` - Initial state
2. `downloading` - Downloading model files from remote
3. `downloaded` - Files downloaded successfully
4. `loading` - Loading model into memory
5. `loaded` - Ready for inference

### Prewarm Flow

When using the prewarm option (see [WhisperKitConfig](/api/core/whisperkit-config)):

1. `unloaded` - Initial state
2. `prewarming` - Specializing model for device
3. `prewarmed` - Specialization complete
4. `loading` - Loading model into memory
5. `loaded` - Ready for inference

### Unload Flow

When unloading a model:

1. `loaded` - Model in memory
2. `unloading` - Freeing memory
3. `unloaded` - Memory freed

## Usage Examples

### Observing State Changes

```swift theme={null}
let whisperKit = try await WhisperKit(
    model: "openai_whisper-base",
    verbose: true
)

// Access current state
if whisperKit.modelState == .loaded {
    print("Model ready for transcription")
}
```

### Using State Callbacks

```swift theme={null}
func handleModelStateChange(oldState: ModelState?, newState: ModelState) {
    print("Model state: \(oldState?.description ?? "none") → \(newState.description)")
    
    switch newState {
    case .downloading:
        showDownloadProgress()
    case .loading:
        showLoadingIndicator()
    case .loaded:
        hideLoadingIndicator()
        enableTranscription()
    case .unloaded:
        disableTranscription()
    default:
        break
    }
}
```

### UI State Binding (SwiftUI)

```swift theme={null}
struct TranscriptionView: View {
    @State private var modelState: ModelState = .unloaded
    
    var body: some View {
        VStack {
            if modelState.isBusy {
                ProgressView(modelState.description)
            } else if modelState == .loaded {
                Button("Start Transcription") {
                    // Start transcription
                }
            }
            
            Text("Status: \(modelState.description)")
                .font(.caption)
        }
    }
}
```

### Checking Multiple States

```swift theme={null}
func canTranscribe(state: ModelState) -> Bool {
    switch state {
    case .loaded:
        return true
    case .loading, .prewarming, .downloading:
        return false  // Or check state.isBusy
    default:
        return false
    }
}
```

## Type Alias

<ResponseField name="ModelStateCallback" type="(_ oldState: ModelState?, _ newState: ModelState) -> Void">
  Callback type invoked when the pipeline's model state changes.

  ```swift theme={null}
  let callback: ModelStateCallback = { oldState, newState in
      print("State changed from \(oldState?.description ?? "none") to \(newState.description)")
  }
  ```
</ResponseField>

## Notes

* `ModelState` is shared between WhisperKit and TTSKit for consistent state management
* The enum is marked `@frozen`, meaning no new cases will be added (guaranteed binary compatibility)
* Use `isBusy` to determine if the model is in a transitional state
* State transitions are managed internally by WhisperKit

## Related Types

* [WhisperKitConfig](/api/core/whisperkit-config)
* [ModelComputeOptions](/api/core/model-compute-options)
