Transcribe live and recorded audio with the Speech framework. Use when implementing SpeechAnalyzer (iOS 26+), SpeechTranscriber, SFSpeechRecognizer, live microphone speech-to-text, audio file transcription, on-device speech models, speech recognition permissions, or custom language models.
83%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
Low
Low-risk findings worth noting
Convert live speech and prerecorded audio to text. Targets modern on-device SpeechAnalyzer (iOS 26+) and legacy SFSpeechRecognizer (iOS 10+).
Add NSSpeechRecognitionUsageDescription and NSMicrophoneUsageDescription to Info.plist. Request speech and microphone authorization before starting recording:
import Speech
import AVFAudio
func requestPermissions() async -> Bool {
let speechAuthorized = await withCheckedContinuation { continuation in
SFSpeechRecognizer.requestAuthorization { status in
continuation.resume(returning: status == .authorized)
}
}
guard speechAuthorized else { return false }
return await AVAudioApplication.requestRecordPermission()
}SpeechAnalyzer delivers modular, asynchronous streaming transcription using SpeechTranscriber:
import Speech
final class LiveTranscriber {
private var analyzer: SpeechAnalyzer?
private var transcriber: SpeechTranscriber?
func startTranscribing(format: AVAudioFormat) async throws {
let transcriber = SpeechTranscriber(locale: Locale(identifier: "en-US"), preset: .transcription)
let analyzer = SpeechAnalyzer(modules: [transcriber])
self.transcriber = transcriber
self.analyzer = analyzer
Task {
for try await result in transcriber.results {
let text = result.text
if result.isFinal {
print("Committed: \(text)")
} else {
print("Partial: \(text)")
}
}
}
try await analyzer.start(inputFormat: format)
}
func appendAudio(buffer: AVAudioPCMBuffer) {
analyzer?.append(buffer)
}
func stop() async throws {
try await analyzer?.finish()
}
}For audio file transcription and backward compatibility:
func transcribeFile(url: URL) async throws -> String {
guard let recognizer = SFSpeechRecognizer(locale: Locale(identifier: "en-US")),
recognizer.isAvailable else {
throw SpeechError.unavailable
}
let request = SFSpeechURLRecognitionRequest(url: url)
request.requiresOnDeviceRecognition = true
return try await withCheckedThrowingContinuation { continuation in
recognizer.recognitionTask(with: request) { result, error in
if let error {
continuation.resume(throwing: error)
} else if let result, result.isFinal {
continuation.resume(returning: result.bestTranscription.formattedString)
}
}
}
}Check asset installation or download language packs before recognition:
let status = await AssetInventory.status(for: .transcription, locale: Locale(identifier: "en-US"))
if status != .installed {
try await AssetInventory.download(for: .transcription, locale: Locale(identifier: "en-US"))
}NSMicrophoneUsageDescription crashes immediately when accessing AVAudioEngine.result.isFinal is true.requiresOnDeviceRecognition is true, ensure model assets are installed via AssetInventory.AVAudioEngine keeps the microphone indicator active in the status bar.NSSpeechRecognitionUsageDescription and NSMicrophoneUsageDescription present in Info.plistSpeechAnalyzer (iOS 26+) used for modern streaming pipelinesthienqo/ios-skills
6bf8b62
Canonical home
since May 23, 2026
Also appears in
on Sep 6, 2026
since May 22, 2026
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.