SpeechAnalyzer Framework Expert
Skill18 starsChanged 58 days agoMITView on GitHub
Implement, migrate, debug, and review on-device transcription with Apple SpeechAnalyzer, SpeechTranscriber, DictationTranscriber, AssetInventory, AnalyzerInput, live microphone audio, and audio-file analysis on iOS 26, macOS 26, visionOS 26, and tvOS 26 where supported. Use for SpeechAnalyzer setup, locale assets and reservations, volatile/final results, AttributedString transcripts, audio conversion, permissions, lifecycle, and migration from SFSpeechRecognizer or Whisper-based solutions. Do not invent beta or later-SDK APIs, assume locale/device support, iterate Foundation Progress as an AsyncSequence, or use SpeechAnalyzer on watchOS.
In this repository14 other files it gives its agents.
- AGENTS.mdAGENTS.md
- CLAUDE.mdCLAUDE.md
- app-intents-widgetsSkill
- Cross-Platform App Development SkillSkill
- iOS Accessibility SkillSkill
- iOS Animation Graphics SkillSkill
- iphone-duo-designSkill
- Memory Leak Diagnosis SkillSkill
- swift-concurrency-migrationSkill
- swiftdata-core-data-migrationsSkill
- Swift Modern Architecture SkillSkill
- Swift Performance Optimization SkillSkill
- SwiftUI Programming SkillSkill
- Swift Unit Testing SkillSkill
The file
Show its rules and text
We split this skill into the rules it gives an agent
17 rules. About 0 are common, 6 are distinctive, and 11 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈6
Distinctive · estimate
This author's own choices. Worth a look.
11
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 8
Use the API surface in the project’s installed SDK.
- Distinctive: line 19
Do not hardcode a language count.
- Distinctive: line 26
Create a transcriber for the resolved locale.
- Very specific: line 29
Create SpeechAnalyzer, supply AnalyzerInput values, and consume transcriber.results in tracked structured work.
- Very specific: line 35
Read examples/basic_setup.swift for a scoped preparation helper that releases its reservation on success and failure.
- Very specific: line 43
Read examples/locale_manager.swift for equivalence lookup, explicit reservation ownership, installation, Foundation Progress handoff, and …
- Very specific: line 57
When volatile reporting is enabled, replace the current volatile segment rather than repeatedly appending it.
- Very specific: line 59
Read examples/error_handling.swift for typed validation errors and correct result accumulation.
- Very specific: line 64
After ending input, call finalizeAndFinishThroughEndOfInput() to drain and finalize, or cancelAndFinishNow() when results are no longer …
- Very specific: line 67
Keep audio callbacks away from MainActor state.
- Very specific: line 68
Do not mark AVFoundation types @unchecked Sendable without a concrete synchronization/ownership invariant.
- Distinctive: line 81
Read these two files together:
- Very specific: line 92
Read examples/file_transcription.swift.
- Very specific: line 96
If SpeechTranscriber.isAvailable is false, disable the feature or evaluate DictationTranscriber on supported platforms and query its locale …
- Very specific: line 97
Keep SFSpeechRecognizer only behind a deliberate lower-OS or feature-gap adapter.
- Distinctive: line 98
Treat migration from Whisper as a product decision: verify supported locale, device hardware, offline behavior, timestamps, custom …
- Distinctive: line 104
Only stable installed APIs are used on the 26 path.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
SpeechAnalyzer Framework
Use the API surface in the project’s installed SDK. This guide is compatibility-first for the stable Xcode 26.6 / iOS 26.5 SDK and does not substitute later beta conveniences into a 26-target implementation.
Compatibility baseline
SpeechAnalyzer,SpeechTranscriber,AssetInventory, andAnalyzerInputrequire iOS 26, macOS 26, visionOS 26, or tvOS 26. They are unavailable on watchOS.DictationTranscriberis available on iOS 26, macOS 26, and visionOS 26, but not tvOS/watchOS.- Build these APIs with Xcode 26 or newer. A lower deployment target requires an availability gate and a legacy or disabled-feature path.
SpeechTranscriber.isAvailableis hardware-sensitive. An OS version check alone is insufficient.- The live microphone example is iOS-only because it configures
AVAudioSessionand requests record permission. - If an SDK 27 beta offers helpers such as capture/input providers or converter types, keep those declarations in a beta-SDK-only source path, add the relevant
#available(iOS 27, macOS 27, ...)runtime gate, and retain the 26 implementation. A stable 26 compiler cannot resolve an unknown symbol merely because it appears inside#available.
Do not hardcode a language count. Query locale support on the running device.
Stable setup sequence
- Check
SpeechTranscriber.isAvailable. - Resolve user input with
SpeechTranscriber.supportedLocale(equivalentTo:); exactLocaleequality can reject a usable regional equivalent. - Reserve the resolved locale with
AssetInventory.reserve(locale:)when the app owns that reservation. - Create a transcriber for the resolved locale.
- Obtain
AssetInventory.assetInstallationRequest(supporting:)and awaitdownloadAndInstall()when it returns a request. - Guard the optional result of
SpeechAnalyzer.bestAvailableAudioFormat(compatibleWith:)before installing an audio path. - Create
SpeechAnalyzer, supplyAnalyzerInputvalues, and consumetranscriber.resultsin tracked structured work. - End input and await an analyzer finish method. Finishing an
AsyncStreamalone does not finish analysis. - Await the result consumer, then release only the locale reservation this operation created.
There is no SpeechTranscriber.allocate(locale:) in the stable 26 SDK. Locale reservation is an AssetInventory responsibility.
Read examples/basic_setup.swift for a scoped preparation helper that releases its reservation on success and failure.
Assets and progress
AssetInventory.reserve(locale:) returns true when it created a new app reservation and false when that locale was already reserved. Release only reservations the current owner created; do not tear down another feature’s reservation. Respect maximumReservedLocales and expose an explicit release action.
AssetInstallationRequest conforms to ProgressReporting. Its progress property is Foundation Progress, not an AsyncSequence. Pass the object to UI/observation code or inspect fractionCompleted; never write for try await over it.
Read examples/locale_manager.swift for equivalence lookup, explicit reservation ownership, installation, Foundation Progress handoff, and release.
Results
The element type is SpeechTranscriber.Result. Use:
result.textfor the most likelyAttributedString;String(result.text.characters)when plain text is required;result.alternativesonly when alternative reporting was configured;result.isFinalto distinguish final from volatile output;result.rangeand configured attributes when reconciling time-indexed text.
There is no SpeechTranscriptionResult type and no result.transcription property in the stable 26 SDK.
When volatile reporting is enabled, replace the current volatile segment rather than repeatedly appending it. Append finalized text once. For editors that can receive overlapping ranges, reconcile by result.range instead of assuming a single volatile phrase.
Read examples/error_handling.swift for typed validation errors and correct result accumulation.
Lifecycle and concurrency
- Store any unstructured result-consumer task and cancel/await it during teardown. Prefer
async letor a task group for finite file transcription. - After ending input, call
finalizeAndFinishThroughEndOfInput()to drain and finalize, orcancelAndFinishNow()when results are no longer needed. - Propagate setup and finite-analysis errors to the awaiting caller. Surface later live-stream failures through explicit state/callbacks rather than throwing inside an unobserved task.
- Guard concurrent starts while permission prompts or model installation are pending.
- Keep audio callbacks away from
MainActorstate. Capture a dedicated synchronized feeder and hop to the main actor only for UI/error delivery. - Do not mark AVFoundation types
@unchecked Sendablewithout a concrete synchronization/ownership invariant.
Live microphone transcription
An iOS host app needs both:
NSSpeechRecognitionUsageDescriptionNSMicrophoneUsageDescription
Request speech and microphone authorization before starting the engine. Configure and activate the app’s AVAudioSession according to the broader audio policy; the sample owns a record-only measurement session and deactivates it on stop. Apps that mix playback, calls, or other recorders need a central session coordinator.
Install the tap only after obtaining a nonoptional analyzer format. Remove the tap, stop the engine, finish input, finalize/cancel the analyzer, await the result task, deactivate the session, and release the owned reservation on every stop/failure path.
Read these two files together:
- examples/live_transcription.swift: permissions, audio session, engine, tracked task, finalization, and reservation lifecycle.
- examples/buffer_converter.swift: synchronized converter recreation when either input or output format changes.
The sample feeder performs bounded conversion in the audio tap and never touches UI-isolated state. Profile this path on supported devices. A production recorder with stricter real-time requirements should use a preallocated/ring-buffer architecture appropriate to its latency budget.
Audio-file transcription
File analysis does not need microphone permission or an iOS audio session. Prepare assets, open AVAudioFile, start analysis with finishAfterFile: true, and consume results with structured concurrency.
Read examples/file_transcription.swift. Invoke it inside withPreparedSpeechTranscriber from the basic example so reservation ownership stays scoped.
Fallback and migration
- If
SpeechTranscriber.isAvailableis false, disable the feature or evaluateDictationTranscriberon supported platforms and query its locale support separately. - Keep
SFSpeechRecognizeronly behind a deliberate lower-OS or feature-gap adapter; its authorization, request, result, and network behavior differ. - Treat migration from Whisper as a product decision: verify supported locale, device hardware, offline behavior, timestamps, custom vocabulary, model/storage policy, latency, and quality on representative audio.
- Out-of-process models reduce model memory in the app process; they do not eliminate the app’s memory limits or the cost of buffers, transcript state, and tasks.
Review checklist
- Deployment target, SDK, device availability, and locale equivalence are checked.
- Only stable installed APIs are used on the 26 path.
- A created reservation is released; an existing shared reservation is preserved.
Progressis observed as Foundation Progress.- Optional audio format is guarded.
- Results use
SpeechTranscriber.Result.textand preserveAttributedStringwhen useful. - Input finish is followed by analyzer finalization/cancellation.
- Result work is stored or structured and all errors have an owner.
- Live capture includes usage descriptions, permission requests, session activation/deactivation, tap removal, and repeated-start protection.
- Audio conversion handles route/input-format changes and does not access main-actor UI state from the tap.
Supporting material
- README.md summarizes platforms and integration requirements.
- examples/basic_setup.swift scopes model preparation and reservation release.
- examples/locale_manager.swift manages locale assets and Progress.
- examples/error_handling.swift handles results and validation failures.
- examples/file_transcription.swift performs finite file analysis.
- examples/live_transcription.swift and examples/buffer_converter.swift form the live iOS example.
- examples/prompts.md contains representative activation prompts.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

