<!--
{
  "availability" : [
    "iOS: 26.0.0 -",
    "iPadOS: 26.0.0 -",
    "macCatalyst: 26.0.0 -",
    "macOS: 26.0.0 -",
    "tvOS: 26.0.0 -",
    "visionOS: 26.0.0 -"
  ],
  "documentType" : "symbol",
  "framework" : "Speech",
  "identifier" : "/documentation/Speech/SpeechAnalyzer",
  "metadataVersion" : "0.1.0",
  "role" : "Class",
  "symbol" : {
    "kind" : "Class",
    "modules" : [
      "Speech"
    ],
    "preciseIdentifier" : "s:6Speech0A8AnalyzerC"
  },
  "title" : "SpeechAnalyzer"
}
-->

# SpeechAnalyzer

Analyzes spoken audio content in various ways and manages the analysis session.

```
final actor SpeechAnalyzer
```

## Overview

The Speech framework provides several modules that can be added to an analyzer to provide specific types of analysis and transcription. Many use cases only need a [`SpeechTranscriber`](/documentation/Speech/SpeechTranscriber) module, which performs speech-to-text transcriptions.

The `SpeechAnalyzer` class is responsible for:

- Holding associated modules
- Accepting audio speech input
- Controlling the overall analysis

Each module is responsible for:

- Providing guidance on acceptable input
- Providing its analysis or transcription output

Analysis is asynchronous. Input, output, and session control are decoupled and typically occur over several different tasks created by you or by the session. In particular, where an Objective-C API might use a delegate to provide results to you, the Swift API’s modules provides their results via an `AsyncSequence`. Similarly, you provide speech input to this API via an `AsyncSequence` you create and populate.

The analyzer can only analyze one input sequence at a time.

### Perform analysis

To perform analysis on audio files and streams, follow these general steps:

1. Create and configure the necessary modules.
2. Ensure the relevant assets are installed or already present. See [`AssetInventory`](/documentation/Speech/AssetInventory).
3. Create an input sequence you can use to provide the spoken audio. See helper classes [`AssetInputSequenceProvider`](/documentation/Speech/AssetInputSequenceProvider) and [`CaptureInputSequenceProvider`](/documentation/Speech/CaptureInputSequenceProvider).
4. Create and configure the analyzer with the modules and input sequence.
5. Supply audio. See helper class [`AnalyzerInputConverter`](/documentation/Speech/AnalyzerInputConverter).
6. Start analysis.
7. Act on results.
8. Finish analysis when desired.

This example shows how you could perform an analysis that transcribes audio using the `SpeechTranscriber` module:

```swift
import Speech

// Step 1: Modules
guard let locale = SpeechTranscriber.supportedLocale(equivalentTo: Locale.current) else {
    /* Note unsupported language */
}
let transcriber = SpeechTranscriber(locale: locale, preset: .transcription)

// Step 2: Assets
if let installationRequest = try await AssetInventory.assetInstallationRequest(supporting: [transcriber]) {
    try await installationRequest.downloadAndInstall()
}

// Step 3: Input sequence
let (inputSequence, inputBuilder) = AsyncStream.makeStream(of: AnalyzerInput.self)

// Step 4: Analyzer
let audioFormat = await SpeechAnalyzer.bestAvailableAudioFormat(compatibleWith: [transcriber])
let analyzer = SpeechAnalyzer(modules: [transcriber])

// Step 5: Supply audio
let converter = AnalyzerInputConverter(analyzerFormat: audioFormat)
Task {
    while /* audio remains */ {
        let buffer = /* Get some audio */
        let inputs = try converter.convert(buffer, at: nil)
        for input in inputs {
            inputBuilder.yield(input)
        }
    }
    let inputs = try converter.flush()
    for input in inputs {
        inputBuilder.yield(input)
    }
    inputBuilder.finish()
}

// Step 7: Act on results
Task {
    do {
        for try await result in transcriber.results {
            let bestTranscription = result.text // an AttributedString
            let plainTextBestTranscription = String(bestTranscription.characters) // a String
            print(plainTextBestTranscription)
        }
    } catch {
        /* Handle error */
    }
}

// Step 6: Perform analysis
let lastSampleTime = try await analyzer.analyzeSequence(inputSequence)

// Step 8: Finish analysis
if let lastSampleTime {
    try await analyzer.finalizeAndFinish(through: lastSampleTime)
} else {
    try analyzer.cancelAndFinishNow()
}
```

### Analyze audio from files or capture devices

To read audio from a file, asset, or capture device such as a microphone, create an [`AssetInputSequenceProvider`](/documentation/Speech/AssetInputSequenceProvider) or [`CaptureInputSequenceProvider`](/documentation/Speech/CaptureInputSequenceProvider) object.

Get the provider object’s [`analyzerInputs`](/documentation/Speech/AssetInputSequenceProvider/analyzerInputs) or [`analyzerInputs`](/documentation/Speech/CaptureInputSequenceProvider/analyzerInputs) property to convert the source’s audio to a supported format and obtain an asynchronous input sequence of the audio. Pass that sequence to [`analyzeSequence(_:)`](/documentation/Speech/SpeechAnalyzer/analyzeSequence(_:)), [`start(inputSequence:)`](/documentation/Speech/SpeechAnalyzer/start(inputSequence:)), or a similar parameter of the analyzer’s initializer.

To end the analysis session after processing the audio track or captured audio, call one of the analyzer’s `finish` methods. Otherwise, by default, the analyzer won’t terminate its result streams and will wait for additional audio input sequences or buffers. See the “Finish analysis” section below for more details.

### Analyze audio from audio buffers

You can analyze audio buffers directly without using [`AssetInputSequenceProvider`](/documentation/Speech/AssetInputSequenceProvider) or [`CaptureInputSequenceProvider`](/documentation/Speech/CaptureInputSequenceProvider).

To do this:

1. Create an asynchronous input sequence of [`AnalyzerInput`](/documentation/Speech/AnalyzerInput) elements that is appropriate for your use case.
2. Supply the input sequence to [`analyzeSequence(_:)`](/documentation/Speech/SpeechAnalyzer/analyzeSequence(_:)), [`start(inputSequence:)`](/documentation/Speech/SpeechAnalyzer/start(inputSequence:)), or a similar parameter of the analyzer’s initializer.
3. Convert each audio buffer to a supported audio format, either on the fly or in advance.
4. Create [`AnalyzerInput`](/documentation/Speech/AnalyzerInput) objects for each buffer.
5. Add the `AnalyzerInput` objects to the input sequence.

To convert `AVAudioBuffer` audio buffers to a supported format as `AnalyzerInput` objects on the fly, use [`AnalyzerInputConverter`](/documentation/Speech/AnalyzerInputConverter).

To convert audio buffers to a supported format in advance or with some other technique:

1. Detemine the format to convert to by calling [`bestAvailableAudioFormat(compatibleWith:)`](/documentation/Speech/SpeechAnalyzer/bestAvailableAudioFormat(compatibleWith:)) or individual modules’ [`availableCompatibleAudioFormats`](/documentation/Speech/SpeechModule/availableCompatibleAudioFormats) methods
2. Convert the audio and create `AnalyzerInput` objects as necessary

To skip past part of an audio stream, omit the buffers you want to skip from the input sequence. You can resume with a later buffer.

When you resume analysis with a later `AVAudioPCMBuffer` buffer, you may need to supply the correct time-code to account for skipped audio. To do this, pass the time-code of the later buffer as the `bufferStartTime` parameter of the corresponding `AnalyzerInput` object.

### Analyze autonomously

You can and usually should perform analysis using the [`analyzeSequence(_:)`](/documentation/Speech/SpeechAnalyzer/analyzeSequence(_:)) or [`analyzeSequence(from:)`](/documentation/Speech/SpeechAnalyzer/analyzeSequence(from:)) methods; those methods work well with Swift structured concurrency techniques. However, you may prefer that the analyzer proceed independently and perform its analysis autonomously as audio input becomes available in a task managed by the analyzer itself.

To use this capability, create the analyzer with one of the initializers that has an input sequence or file parameter, or call [`start(inputSequence:)`](/documentation/Speech/SpeechAnalyzer/start(inputSequence:)) or [`start(inputAudioFile:finishAfterFile:)`](/documentation/Speech/SpeechAnalyzer/start(inputAudioFile:finishAfterFile:)). To end the analysis of that input only and start analysis of different input, call one of the `start` methods again. To end the analysis session when the input ends, call [`finalizeAndFinishThroughEndOfInput()`](/documentation/Speech/SpeechAnalyzer/finalizeAndFinishThroughEndOfInput()).

### Control processing and timing of results

Modules deliver results periodically, but you can manually synchronize their processing and delivery to outside cues.

To deliver a result for a particular time-code, call [`finalize(through:)`](/documentation/Speech/SpeechAnalyzer/finalize(through:)). To cancel processing of results that are no longer of interest, call [`cancelAnalysis(before:)`](/documentation/Speech/SpeechAnalyzer/cancelAnalysis(before:)).

### Improve responsiveness

By default, the analyzer and modules load the system resources that they require lazily, and unload those resources when they’re deallocated.

To proactively load system resources and “preheat” the analyzer, call [`prepareToAnalyze(in:)`](/documentation/Speech/SpeechAnalyzer/prepareToAnalyze(in:)) after setting its modules. This may improve how quickly the modules return their first results.

To delay or prevent unloading an analyzer’s resources — caching them for later use by a different analyzer instance — you can select a [`SpeechAnalyzer.Options.ModelRetention`](/documentation/Speech/SpeechAnalyzer/Options/ModelRetention-swift.enum) option and create the analyzer with an appropriate [`SpeechAnalyzer.Options`](/documentation/Speech/SpeechAnalyzer/Options) object.

To set the priority of analysis work, create the analyzer with a [`SpeechAnalyzer.Options`](/documentation/Speech/SpeechAnalyzer/Options) object with the desired `priority` value.

Specific modules may also offer options that improve responsiveness.

### Finish analysis

To end an analysis session, you must use one of the analyzer’s `finish` methods or parameters, or deallocate the analyzer.

When the analysis session transitions to the *finished* state:

- The analyzer won’t consume additional input from the input sequence (but note that it doesn’t drain or terminate the sequence)
- Most methods won’t do anything; in particular, the analyzer won’t accept different input sequences or modules
- Module result streams terminate and modules won’t publish additional results, though the app can continue to iterate over already-published results

> Note: While you can terminate the input sequence you created with a method such as `AsyncStream.Continuation.finish()`, terminating the input sequence does *not* generally finish the analysis session, and you can continue the session with a different input sequence. (See ``doc://com.apple.speech/documentation/Speech/SpeechAnalyzer/finalizeAndFinishThroughEndOfInput()`` for an exception.)

### Respond to errors

When the analyzer or its modules’ result streams throw an error, the analysis session becomes finished as described above, and the same error (or a `CancellationError`) is thrown from all waiting methods and result streams.

When this happens, you may wish to terminate the input sequence, or create a new analyzer to continue working on the remaining (and any additional) input.

### Manage simultaneous analyses

The system normally limits simultaneous analyses to a conservative number, considering hardware capabilities of different devices. If you exceed that number, the system throws an [`insufficientResources`](/documentation/Speech/SFSpeechError/Code/insufficientResources) error.

However, under certain use cases, the hardware may be able to accommodate additional simultaneous analyses; for example, several simultaneous transcription sessions may use the same language and settings, or only receive audio in an interleaved schedule. To support these use cases, you can override the system to ignore the predefined conservative system resource limits.

To override the normal limits, create an analyzer with a [`SpeechAnalyzer.Options`](/documentation/Speech/SpeechAnalyzer/Options) object with its [`ignoresResourceLimits`](/documentation/Speech/SpeechAnalyzer/Options/ignoresResourceLimits) value set to `true`. The system allows an unlimited number of analyzers configured with this option. However, the hardware requirements of numerous analyzers will eventually exceed the system’s actual capacity, and one or more of the analyzers will fail, throwing an unpredictable error.

> Warning: When using this option, test your app on a variety of devices under a variety of scenarios to experimentally determine how many analyzers you can reliably create and expect to function. Consider how to recover in the event one or more analyzers fail.

## Topics

### Creating an analyzer

[`convenience init(modules: [any SpeechModule], options: SpeechAnalyzer.Options?)`](/documentation/Speech/SpeechAnalyzer/init(modules:options:))

Creates an analyzer.

[`convenience init<InputSequence>(inputSequence: InputSequence, modules: [any SpeechModule], options: SpeechAnalyzer.Options?, analysisContext: AnalysisContext, volatileRangeChangedHandler: sending ((CMTimeRange, Bool, Bool) -> Void)?)`](/documentation/Speech/SpeechAnalyzer/init(inputSequence:modules:options:analysisContext:volatileRangeChangedHandler:))

Creates an analyzer and begins analysis.

[`convenience init(inputAudioFile: AVAudioFile, modules: [any SpeechModule], options: SpeechAnalyzer.Options?, analysisContext: AnalysisContext, finishAfterFile: Bool, volatileRangeChangedHandler: sending ((CMTimeRange, Bool, Bool) -> Void)?) async throws`](/documentation/Speech/SpeechAnalyzer/init(inputAudioFile:modules:options:analysisContext:finishAfterFile:volatileRangeChangedHandler:))

Creates an analyzer and begins analysis on an audio file.

[`struct Options`](/documentation/Speech/SpeechAnalyzer/Options)

Analysis processing options.

### Managing modules

[`func setModules([any SpeechModule]) async throws`](/documentation/Speech/SpeechAnalyzer/setModules(_:))

Adds or removes modules.

[`var modules: [any SpeechModule]`](/documentation/Speech/SpeechAnalyzer/modules)

The modules performing analysis on the audio input.

### Performing analysis

[`func analyzeSequence<InputSequence>(InputSequence) async throws -> CMTime?`](/documentation/Speech/SpeechAnalyzer/analyzeSequence(_:))

Analyzes an input sequence, returning when the sequence terminates.

[`func analyzeSequence(from: AVAudioFile) async throws -> CMTime?`](/documentation/Speech/SpeechAnalyzer/analyzeSequence(from:))

Analyzes an input sequence created from an audio file, returning when the file has been read.

### Performing autonomous analysis

[`func start<InputSequence>(inputSequence: InputSequence) async throws`](/documentation/Speech/SpeechAnalyzer/start(inputSequence:))

Starts analysis of an input sequence and returns immediately.

[`func start(inputAudioFile: AVAudioFile, finishAfterFile: Bool) async throws`](/documentation/Speech/SpeechAnalyzer/start(inputAudioFile:finishAfterFile:))

Starts analysis of an input sequence created from an audio file and returns immediately.

### Finalizing and cancelling results

[`func cancelAnalysis(before: CMTime)`](/documentation/Speech/SpeechAnalyzer/cancelAnalysis(before:))

Stops analyzing audio predating the given time.

[`func finalize(through: CMTime?) async throws`](/documentation/Speech/SpeechAnalyzer/finalize(through:))

Finalizes the modules’ analyses.

### Finishing analysis

[`func cancelAndFinishNow() async`](/documentation/Speech/SpeechAnalyzer/cancelAndFinishNow())

Finishes analysis immediately.

[`func finalizeAndFinishThroughEndOfInput() async throws`](/documentation/Speech/SpeechAnalyzer/finalizeAndFinishThroughEndOfInput())

Finishes analysis after an audio input sequence has been terminated and fully consumed and the modules’ results are finalized.

[`func finalizeAndFinish(through: CMTime) async throws`](/documentation/Speech/SpeechAnalyzer/finalizeAndFinish(through:))

Finishes analysis after finalizing results for a given time-code.

[`func finish(after: CMTime) async throws`](/documentation/Speech/SpeechAnalyzer/finish(after:))

Finishes analysis once input for a given time is consumed.

### Determining audio formats

[`static func bestAvailableAudioFormat(compatibleWith: [any SpeechModule]) async -> AVAudioFormat?`](/documentation/Speech/SpeechAnalyzer/bestAvailableAudioFormat(compatibleWith:))

Retrieves the best-quality audio format that the specified modules can work with, from assets installed on the device.

[`static func bestAvailableAudioFormat(compatibleWith: [any SpeechModule], considering: AVAudioFormat?) async -> AVAudioFormat?`](/documentation/Speech/SpeechAnalyzer/bestAvailableAudioFormat(compatibleWith:considering:))

Retrieves the best-quality audio format that the specified modules can work with, taking into account the natural format of the audio and assets installed on the device.

### Improving responsiveness

[`func prepareToAnalyze(in: AVAudioFormat?) async throws`](/documentation/Speech/SpeechAnalyzer/prepareToAnalyze(in:))

Prepares the analyzer to begin work with minimal startup delay.

[`func prepareToAnalyze(in: AVAudioFormat?, withProgressReadyHandler: sending ((Progress) -> Void)?) async throws`](/documentation/Speech/SpeechAnalyzer/prepareToAnalyze(in:withProgressReadyHandler:))

Prepares the analyzer to begin work with minimal startup delay, reporting the progress of that preparation.

### Monitoring analysis

[`func setVolatileRangeChangedHandler(sending ((CMTimeRange, Bool, Bool) -> Void)?)`](/documentation/Speech/SpeechAnalyzer/setVolatileRangeChangedHandler(_:))

A closure that the analyzer calls when the volatile range changes.

[`var volatileRange: CMTimeRange?`](/documentation/Speech/SpeechAnalyzer/volatileRange)

The range of results that can change.

### Managing contexts

[`func setContext(AnalysisContext) async throws`](/documentation/Speech/SpeechAnalyzer/setContext(_:))

Sets contextual information to improve or inform the analysis.

[`var context: AnalysisContext`](/documentation/Speech/SpeechAnalyzer/context)

An object containing contextual information.

## Relationships

### Conforms To

[`Sendable`](/documentation/Swift/Sendable)

[`Actor`](/documentation/Swift/Actor)

[`SendableMetatype`](/documentation/Swift/SendableMetatype)

---

Copyright &copy; 2026 Apple Inc. All rights reserved. | [Terms of Use](https://www.apple.com/legal/internet-services/terms/site.html) | [Privacy Policy](https://www.apple.com/privacy/privacy-policy)