{"id":"dffc3578-e656-42de-8836-7c01d6cef3c5","shortId":"cqWVM5","kind":"skill","title":"speech-recognition","tagline":"Transcribe speech to text using the Speech framework. Use when implementing live microphone transcription with AVAudioEngine, recognizing pre-recorded audio files, configuring on-device vs server-based recognition, handling authorization flows, or adopting the new SpeechAnalyzer ","description":"# Speech Recognition\n\nTranscribe live and pre-recorded audio to text using Apple's Speech framework.\nCovers `SFSpeechRecognizer` (iOS 10+) and the new `SpeechAnalyzer` API (iOS 26+).\n\n## Contents\n\n- [SpeechAnalyzer (iOS 26+)](#speechanalyzer-ios-26)\n- [SFSpeechRecognizer Setup](#sfspeechrecognizer-setup)\n- [Authorization](#authorization)\n- [Live Microphone Transcription](#live-microphone-transcription)\n- [Pre-Recorded Audio File Recognition](#pre-recorded-audio-file-recognition)\n- [On-Device vs Server Recognition](#on-device-vs-server-recognition)\n- [Handling Results](#handling-results)\n- [Common Mistakes](#common-mistakes)\n- [Review Checklist](#review-checklist)\n- [References](#references)\n\n## SpeechAnalyzer (iOS 26+)\n\n`SpeechAnalyzer` is an actor-based API introduced in iOS 26 that replaces\n`SFSpeechRecognizer` for new projects. It uses Swift concurrency, `AsyncSequence`\nfor results, and supports modular analysis via `SpeechTranscriber`.\n\n### Basic transcription with SpeechAnalyzer\n\n```swift\nimport Speech\n\n// 1. Create a transcriber module\nguard let locale = SpeechTranscriber.supportedLocale(\n    equivalentTo: Locale.current\n) else { return }\nlet transcriber = SpeechTranscriber(locale: locale, preset: .offlineTranscription)\n\n// 2. Ensure assets are installed\nif let request = try await AssetInventory.assetInstallationRequest(\n    supporting: [transcriber]\n) {\n    try await request.downloadAndInstall()\n}\n\n// 3. Create input stream and analyzer\nlet (inputSequence, inputBuilder) = AsyncStream.makeStream(of: AnalyzerInput.self)\nlet audioFormat = await SpeechAnalyzer.bestAvailableAudioFormat(\n    compatibleWith: [transcriber]\n)\nlet analyzer = SpeechAnalyzer(modules: [transcriber])\n\n// 4. Feed audio buffers (from AVAudioEngine or file)\nTask {\n    // Append PCM buffers converted to audioFormat\n    let pcmBuffer: AVAudioPCMBuffer = // ... your audio buffer\n    inputBuilder.yield(AnalyzerInput(buffer: pcmBuffer))\n    inputBuilder.finish()\n}\n\n// 5. Consume results\nTask {\n    for try await result in transcriber.results {\n        let text = String(result.text.characters)\n        print(text)\n    }\n}\n\n// 6. Run analysis\nlet lastSampleTime = try await analyzer.analyzeSequence(inputSequence)\n\n// 7. Finalize\nif let lastSampleTime {\n    try await analyzer.finalizeAndFinish(through: lastSampleTime)\n} else {\n    try analyzer.cancelAndFinishNow()\n}\n```\n\n### Transcribing an audio file with SpeechAnalyzer\n\n```swift\nlet transcriber = SpeechTranscriber(locale: locale, preset: .offlineTranscription)\nlet audioFile = try AVAudioFile(forReading: fileURL)\nlet analyzer = SpeechAnalyzer(\n    inputAudioFile: audioFile, modules: [transcriber], finishAfterFile: true\n)\nfor try await result in transcriber.results {\n    print(String(result.text.characters))\n}\n```\n\n### Key differences from SFSpeechRecognizer\n\n| Feature | SFSpeechRecognizer | SpeechAnalyzer |\n|---|---|---|\n| Concurrency | Callbacks/delegates | async/await + AsyncSequence |\n| Type | `class` | `actor` |\n| Modules | Monolithic | Composable (`SpeechTranscriber`, `SpeechDetector`) |\n| Audio input | `append(_:)` on request | `AsyncStream<AnalyzerInput>` |\n| Availability | iOS 10+ | iOS 26+ |\n| On-device | `requiresOnDeviceRecognition` | Asset-based via `AssetInventory` |\n\n## SFSpeechRecognizer Setup\n\n### Creating a recognizer with locale\n\n```swift\nimport Speech\n\n// Default locale (user's current language)\nlet recognizer = SFSpeechRecognizer()\n\n// Specific locale\nlet recognizer = SFSpeechRecognizer(locale: Locale(identifier: \"en-US\"))\n\n// Check if recognition is available for this locale\nguard let recognizer, recognizer.isAvailable else {\n    print(\"Speech recognition not available\")\n    return\n}\n```\n\n### Monitoring availability changes\n\n```swift\nfinal class SpeechManager: NSObject, SFSpeechRecognizerDelegate {\n    private let recognizer = SFSpeechRecognizer()!\n\n    override init() {\n        super.init()\n        recognizer.delegate = self\n    }\n\n    func speechRecognizer(\n        _ speechRecognizer: SFSpeechRecognizer,\n        availabilityDidChange available: Bool\n    ) {\n        // Update UI — disable record button when unavailable\n    }\n}\n```\n\n## Authorization\n\nRequest **both** speech recognition and microphone permissions before starting\nlive transcription. Add these keys to `Info.plist`:\n\n- `NSSpeechRecognitionUsageDescription`\n- `NSMicrophoneUsageDescription`\n\n```swift\nimport Speech\nimport AVFoundation\n\nfunc requestPermissions() async -> Bool {\n    let speechStatus = await withCheckedContinuation { continuation in\n        SFSpeechRecognizer.requestAuthorization { status in\n            continuation.resume(returning: status)\n        }\n    }\n    guard speechStatus == .authorized else { return false }\n\n    let micStatus: Bool\n    if #available(iOS 17, *) {\n        micStatus = await AVAudioApplication.requestRecordPermission()\n    } else {\n        micStatus = await withCheckedContinuation { continuation in\n            AVAudioSession.sharedInstance().requestRecordPermission { granted in\n                continuation.resume(returning: granted)\n            }\n        }\n    }\n    return micStatus\n}\n```\n\n## Live Microphone Transcription\n\nThe standard pattern: `AVAudioEngine` captures microphone audio → buffers are\nappended to `SFSpeechAudioBufferRecognitionRequest` → results stream in.\n\n```swift\nimport Speech\nimport AVFoundation\n\nfinal class LiveTranscriber {\n    private let recognizer = SFSpeechRecognizer(locale: Locale(identifier: \"en-US\"))!\n    private let audioEngine = AVAudioEngine()\n    private var recognitionRequest: SFSpeechAudioBufferRecognitionRequest?\n    private var recognitionTask: SFSpeechRecognitionTask?\n\n    func startTranscribing() throws {\n        // Cancel any in-progress task\n        recognitionTask?.cancel()\n        recognitionTask = nil\n\n        // Configure audio session\n        let audioSession = AVAudioSession.sharedInstance()\n        try audioSession.setCategory(.record, mode: .measurement, options: .duckOthers)\n        try audioSession.setActive(true, options: .notifyOthersOnDeactivation)\n\n        // Create request\n        let request = SFSpeechAudioBufferRecognitionRequest()\n        request.shouldReportPartialResults = true\n        self.recognitionRequest = request\n\n        // Start recognition task\n        recognitionTask = recognizer.recognitionTask(with: request) { result, error in\n            if let result {\n                let text = result.bestTranscription.formattedString\n                print(\"Transcription: \\(text)\")\n\n                if result.isFinal {\n                    self.stopTranscribing()\n                }\n            }\n            if let error {\n                print(\"Recognition error: \\(error)\")\n                self.stopTranscribing()\n            }\n        }\n\n        // Install audio tap\n        let inputNode = audioEngine.inputNode\n        let recordingFormat = inputNode.outputFormat(forBus: 0)\n        inputNode.installTap(onBus: 0, bufferSize: 1024, format: recordingFormat) {\n            buffer, _ in\n            request.append(buffer)\n        }\n\n        audioEngine.prepare()\n        try audioEngine.start()\n    }\n\n    func stopTranscribing() {\n        audioEngine.stop()\n        audioEngine.inputNode.removeTap(onBus: 0)\n        recognitionRequest?.endAudio()\n        recognitionRequest = nil\n        recognitionTask?.cancel()\n        recognitionTask = nil\n    }\n}\n```\n\n## Pre-Recorded Audio File Recognition\n\nUse `SFSpeechURLRecognitionRequest` for audio files on disk:\n\n```swift\nfunc transcribeFile(at url: URL) async throws -> String {\n    guard let recognizer = SFSpeechRecognizer(), recognizer.isAvailable else {\n        throw SpeechError.unavailable\n    }\n    let request = SFSpeechURLRecognitionRequest(url: url)\n    request.shouldReportPartialResults = false\n\n    return try await withCheckedThrowingContinuation { continuation in\n        recognizer.recognitionTask(with: request) { result, error in\n            if let error {\n                continuation.resume(throwing: error)\n            } else if let result, result.isFinal {\n                continuation.resume(\n                    returning: result.bestTranscription.formattedString\n                )\n            }\n        }\n    }\n}\n```\n\n## On-Device vs Server Recognition\n\nOn-device recognition (iOS 13+) works offline but supports fewer locales:\n\n```swift\nlet recognizer = SFSpeechRecognizer(locale: Locale(identifier: \"en-US\"))!\n\n// Check if on-device is supported for this locale\nif recognizer.supportsOnDeviceRecognition {\n    let request = SFSpeechAudioBufferRecognitionRequest()\n    request.requiresOnDeviceRecognition = true  // Force on-device\n}\n```\n\n> **Tip:** On-device recognition avoids network latency and the one-minute\n> audio limit imposed by server-based recognition. However, accuracy may be\n> lower and not all locales are supported. Check `supportsOnDeviceRecognition`\n> before forcing on-device mode.\n\n## Handling Results\n\n### Partial vs final results\n\n```swift\nlet request = SFSpeechAudioBufferRecognitionRequest()\nrequest.shouldReportPartialResults = true  // default is true\n\nrecognizer.recognitionTask(with: request) { result, error in\n    guard let result else { return }\n\n    if result.isFinal {\n        // Final transcription — recognition is complete\n        let final = result.bestTranscription.formattedString\n    } else {\n        // Partial result — may change as more audio is processed\n        let partial = result.bestTranscription.formattedString\n    }\n}\n```\n\n### Accessing alternative transcriptions and confidence\n\n```swift\nrecognizer.recognitionTask(with: request) { result, error in\n    guard let result else { return }\n\n    // Best transcription\n    let best = result.bestTranscription\n\n    // All alternatives (sorted by confidence, descending)\n    for transcription in result.transcriptions {\n        for segment in transcription.segments {\n            print(\"\\(segment.substring): \\(segment.confidence)\")\n        }\n    }\n}\n```\n\n### Adding punctuation (iOS 16+)\n\n```swift\nlet request = SFSpeechAudioBufferRecognitionRequest()\nrequest.addsPunctuation = true\n```\n\n### Contextual strings\n\nImprove recognition of domain-specific terms:\n\n```swift\nlet request = SFSpeechAudioBufferRecognitionRequest()\nrequest.contextualStrings = [\"SwiftUI\", \"Xcode\", \"CloudKit\"]\n```\n\n## Common Mistakes\n\n### Not requesting both speech and microphone authorization\n\n```swift\n// ❌ DON'T: Only request speech authorization for live audio\nSFSpeechRecognizer.requestAuthorization { status in\n    // Missing microphone permission — audio engine will fail\n    self.startRecording()\n}\n\n// ✅ DO: Request both permissions before recording\nSFSpeechRecognizer.requestAuthorization { status in\n    guard status == .authorized else { return }\n    AVAudioSession.sharedInstance().requestRecordPermission { granted in\n        guard granted else { return }\n        self.startRecording()\n    }\n}\n```\n\n### Not handling availability changes\n\n```swift\n// ❌ DON'T: Assume recognizer stays available after initial check\nlet recognizer = SFSpeechRecognizer()!\n// Recognition may fail if network drops or locale changes\n\n// ✅ DO: Monitor availability via delegate\nrecognizer.delegate = self\nfunc speechRecognizer(\n    _ speechRecognizer: SFSpeechRecognizer,\n    availabilityDidChange available: Bool\n) {\n    recordButton.isEnabled = available\n}\n```\n\n### Not stopping the audio engine when recognition ends\n\n```swift\n// ❌ DON'T: Leave audio engine running after recognition finishes\nrecognizer.recognitionTask(with: request) { result, error in\n    if result?.isFinal == true {\n        // Audio engine still running, wasting resources and battery\n    }\n}\n\n// ✅ DO: Clean up all audio resources\nrecognizer.recognitionTask(with: request) { result, error in\n    if result?.isFinal == true || error != nil {\n        self.audioEngine.stop()\n        self.audioEngine.inputNode.removeTap(onBus: 0)\n        self.recognitionRequest?.endAudio()\n        self.recognitionRequest = nil\n    }\n}\n```\n\n### Assuming on-device recognition is available for all locales\n\n```swift\n// ❌ DON'T: Force on-device without checking support\nlet request = SFSpeechAudioBufferRecognitionRequest()\nrequest.requiresOnDeviceRecognition = true // May silently fail\n\n// ✅ DO: Check support before requiring on-device\nif recognizer.supportsOnDeviceRecognition {\n    request.requiresOnDeviceRecognition = true\n} else {\n    // Fall back to server-based or inform user\n}\n```\n\n### Not handling the one-minute recognition limit\n\n```swift\n// ❌ DON'T: Start one long continuous recognition session\nfunc startRecording() {\n    // This will be cut off after ~60 seconds (server-based)\n}\n\n// ✅ DO: Restart recognition when approaching the limit\nfunc startRecording() {\n    // Use a timer to restart before the limit\n    recognitionTimer = Timer.scheduledTimer(withTimeInterval: 55, repeats: false) {\n        [weak self] _ in\n        self?.restartRecognition()\n    }\n}\n```\n\n### Creating multiple simultaneous recognition tasks\n\n```swift\n// ❌ DON'T: Start a new task without canceling the previous one\nfunc startRecording() {\n    recognitionTask = recognizer.recognitionTask(with: request) { ... }\n    // Previous task is still running — undefined behavior\n}\n\n// ✅ DO: Cancel existing task before creating a new one\nfunc startRecording() {\n    recognitionTask?.cancel()\n    recognitionTask = nil\n    recognitionTask = recognizer.recognitionTask(with: request) { ... }\n}\n```\n\n## Review Checklist\n\n- [ ] `NSSpeechRecognitionUsageDescription` is in Info.plist\n- [ ] `NSMicrophoneUsageDescription` is in Info.plist (if using live audio)\n- [ ] Authorization is requested before starting recognition\n- [ ] `SFSpeechRecognizerDelegate` is set to handle `availabilityDidChange`\n- [ ] Audio engine is stopped and tap removed when recognition ends\n- [ ] `recognitionRequest.endAudio()` is called when done recording\n- [ ] Previous `recognitionTask` is canceled before starting a new one\n- [ ] `supportsOnDeviceRecognition` is checked before requiring on-device mode\n- [ ] Partial results are handled separately from final (`isFinal`) results\n- [ ] One-minute limit is accounted for in server-based recognition\n- [ ] For iOS 26+: `AssetInventory` assets are installed before using `SpeechAnalyzer`\n- [ ] For iOS 26+: `SpeechTranscriber.supportedLocale(equivalentTo:)` is checked\n\n## References\n\n- [Speech framework](https://sosumi.ai/documentation/speech)\n- [SpeechAnalyzer](https://sosumi.ai/documentation/speech/speechanalyzer)\n- [SpeechTranscriber](https://sosumi.ai/documentation/speech/speechtranscriber)\n- [SFSpeechRecognizer](https://sosumi.ai/documentation/speech/sfspeechrecognizer)\n- [SFSpeechAudioBufferRecognitionRequest](https://sosumi.ai/documentation/speech/sfspeechaudiobufferrecognitionrequest)\n- [SFSpeechURLRecognitionRequest](https://sosumi.ai/documentation/speech/sfspeechurlrecognitionrequest)\n- [SFSpeechRecognitionResult](https://sosumi.ai/documentation/speech/sfspeechrecognitionresult)\n- [SFSpeechRecognitionRequest](https://sosumi.ai/documentation/speech/sfspeechrecognitionrequest)\n- [AssetInventory](https://sosumi.ai/documentation/speech/assetinventory)\n- [Asking Permission to Use Speech Recognition](https://sosumi.ai/documentation/speech/asking-permission-to-use-speech-recognition)\n- [Recognizing Speech in Live Audio](https://sosumi.ai/documentation/speech/recognizing-speech-in-live-audio)","tags":["speech","recognition","swift","ios","skills","dpearson2699","accessibility","agent-skills","ai-coding","apple","claude-code","codex-skills"],"capabilities":["skill","source-dpearson2699","skill-speech-recognition","topic-accessibility","topic-agent-skills","topic-ai-coding","topic-apple","topic-claude-code","topic-codex-skills","topic-cursor-skills","topic-ios","topic-ios-development","topic-liquid-glass","topic-localization","topic-mapkit"],"categories":["swift-ios-skills"],"synonyms":[],"warnings":[],"endpointUrl":"https://skills.sh/dpearson2699/swift-ios-skills/speech-recognition","protocol":"skill","transport":"skills-sh","auth":{"type":"none","details":{"cli":"npx skills add dpearson2699/swift-ios-skills","source_repo":"https://github.com/dpearson2699/swift-ios-skills","install_from":"skills.sh"}},"qualityScore":"0.700","qualityRationale":"deterministic score 0.70 from registry signals: · indexed on github topic:agent-skills · 599 github stars · SKILL.md body (15,324 chars)","verified":false,"liveness":"unknown","lastLivenessCheck":null,"agentReviews":{"count":0,"score_avg":null,"cost_usd_avg":null,"success_rate":null,"latency_p50_ms":null,"narrative_summary":null,"summary_updated_at":null},"enrichmentModel":"deterministic:skill-github:v1","enrichmentVersion":1,"enrichedAt":"2026-05-18T18:53:44.210Z","embedding":null,"createdAt":"2026-04-18T20:34:18.821Z","updatedAt":"2026-05-18T18:53:44.210Z","lastSeenAt":"2026-05-18T18:53:44.210Z","tsv":"'/documentation/speech)':1366 '/documentation/speech/asking-permission-to-use-speech-recognition)':1407 '/documentation/speech/assetinventory)':1398 '/documentation/speech/recognizing-speech-in-live-audio)':1415 '/documentation/speech/sfspeechaudiobufferrecognitionrequest)':1382 '/documentation/speech/sfspeechrecognitionrequest)':1394 '/documentation/speech/sfspeechrecognitionresult)':1390 '/documentation/speech/sfspeechrecognizer)':1378 '/documentation/speech/sfspeechurlrecognitionrequest)':1386 '/documentation/speech/speechanalyzer)':1370 '/documentation/speech/speechtranscriber)':1374 '0':653,656,673,1101 '1':173 '10':62,361 '1024':658 '13':756 '16':925 '17':506 '2':193 '26':69,73,77,135,146,363,1346,1356 '3':209 '4':232 '5':258 '55':1206 '6':274 '60':1181 '7':283 'access':883 'account':1337 'accuraci':816 'actor':140,347 'actor-bas':139 'ad':922 'add':466 'adopt':39 'altern':884,906 'analysi':163,276 'analyz':214,228,317 'analyzer.analyzesequence':281 'analyzer.cancelandfinishnow':295 'analyzer.finalizeandfinish':290 'analyzerinput':254 'analyzerinput.self':220 'api':67,142 'append':241,355,537 'appl':55 'approach':1190 'ask':1399 'asset':195,369,1348 'asset-bas':368 'assetinventori':372,1347,1395 'assetinventory.assetinstallationrequest':203 'assum':1009,1106 'async':480,701 'async/await':343 'asyncsequ':157,344 'asyncstream':358 'asyncstream.makestream':218 'audio':24,51,95,101,234,251,298,353,534,587,644,685,691,807,877,967,974,1047,1056,1072,1084,1276,1289,1412 'audioengin':563 'audioengine.inputnode':648 'audioengine.inputnode.removetap':671 'audioengine.prepare':665 'audioengine.start':667 'audioengine.stop':670 'audiofil':311,320 'audioformat':222,246 'audiosess':590 'audiosession.setactive':600 'audiosession.setcategory':593 'author':36,83,84,454,496,957,964,990,1277 'avail':359,407,420,423,445,504,1004,1012,1030,1040,1043,1112 'availabilitydidchang':444,1039,1288 'avaudioapplication.requestrecordpermission':509 'avaudioengin':19,237,531,564 'avaudiofil':313 'avaudiopcmbuff':249 'avaudiosession.sharedinstance':516,591,993 'avfound':477,547 'avoid':799 'await':202,207,223,264,280,289,327,484,508,512,721 'back':1148 'base':33,141,370,813,1152,1185,1342 'basic':166 'batteri':1079 'behavior':1243 'best':900,903 'bool':446,481,502,1041 'buffer':235,243,252,255,535,661,664 'buffers':657 'button':451 'call':1301 'callbacks/delegates':342 'cancel':576,583,679,1227,1245,1256,1308 'captur':532 'chang':424,874,1005,1027 'check':403,773,826,1015,1124,1135,1316,1360 'checklist':127,130,1264 'class':346,427,549 'clean':1081 'cloudkit':948 'common':121,124,949 'common-mistak':123 'compatiblewith':225 'complet':866 'compos':350 'concurr':156,341 'confid':887,909 'configur':26,586 'consum':259 'content':70 'contextu':932 'continu':486,514,723,1170 'continuation.resume':491,520,734,742 'convert':244 'cover':59 'creat':174,210,375,604,1214,1249 'current':387 'cut':1178 'default':383,846 'deleg':1032 'descend':910 'devic':29,106,112,366,747,753,777,793,797,832,1109,1122,1141,1321 'differ':335 'disabl':449 'disk':694 'domain':938 'domain-specif':937 'done':1303 'drop':1024 'duckoth':598 'els':184,293,415,497,510,709,737,858,870,898,991,999,1146 'en':401,559,771 'en-us':400,558,770 'end':1051,1298 'endaudio':675,1103 'engin':975,1048,1057,1073,1290 'ensur':194 'equivalentto':182,1358 'error':621,637,640,641,729,733,736,853,893,1066,1090,1096 'exist':1246 'fail':977,1021,1133 'fall':1147 'fals':499,718,1208 'featur':338 'feed':233 'fewer':761 'file':25,96,102,239,299,686,692 'fileurl':315 'final':284,426,548,838,862,868,1329 'finish':1061 'finishafterfil':323 'flow':37 'forbus':652 'forc':790,829,1119 'format':659 'forread':314 'framework':11,58,1363 'func':440,478,573,668,696,1035,1173,1193,1231,1253 'grant':518,522,995,998 'guard':178,411,494,704,855,895,988,997 'handl':35,116,119,834,1003,1157,1287,1326 'handling-result':118 'howev':815 'identifi':399,557,769 'implement':14 'import':171,381,474,476,544,546 'impos':809 'improv':934 'in-progress':578 'info.plist':470,1268,1272 'inform':1154 'init':436 'initi':1014 'input':211,354 'inputaudiofil':319 'inputbuild':217 'inputbuilder.finish':257 'inputbuilder.yield':253 'inputnod':647 'inputnode.installtap':654 'inputnode.outputformat':651 'inputsequ':216,282 'instal':197,643,1350 'introduc':143 'io':61,68,72,76,134,145,360,362,505,755,924,1345,1355 'isfin':1070,1094,1330 'key':334,468 'languag':388 'lastsampletim':278,287,292 'latenc':801 'leav':1055 'let':179,186,199,215,221,227,247,268,277,286,303,310,316,389,394,412,432,482,500,552,562,589,606,624,626,636,646,649,705,712,732,739,764,785,841,856,867,880,896,902,927,942,1016,1126 'limit':808,1163,1192,1202,1335 'live':15,46,85,89,464,525,966,1275,1411 'live-microphone-transcript':88 'livetranscrib':550 'local':180,189,190,306,307,379,384,393,397,398,410,555,556,762,767,768,782,823,1026,1115 'locale.current':183 'long':1169 'lower':819 'may':817,873,1020,1131 'measur':596 'microphon':16,86,90,460,526,533,956,972 'micstatus':501,507,511,524 'minut':806,1161,1334 'miss':971 'mistak':122,125,950 'mode':595,833,1322 'modul':177,230,321,348 'modular':162 'monitor':422,1029 'monolith':349 'multipl':1215 'network':800,1023 'new':41,65,151,1224,1251,1312 'nil':585,677,681,1097,1105,1258 'notifyothersondeactiv':603 'nsmicrophoneusagedescript':472,1269 'nsobject':429 'nsspeechrecognitionusagedescript':471,1265 'offlin':758 'offlinetranscript':192,309 'on-devic':27,104,364,745,751,775,791,795,830,1107,1120,1139,1319 'on-device-vs-server-recognit':110 'onbus':655,672,1100 'one':805,1160,1168,1230,1252,1313,1333 'one-minut':804,1159,1332 'option':597,602 'overrid':435 'partial':836,871,881,1323 'pattern':530 'pcm':242 'pcmbuffer':248,256 'permiss':461,973,982,1400 'pre':22,49,93,99,683 'pre-record':21,48,92,682 'pre-recorded-audio-file-recognit':98 'preset':191,308 'previous':1229,1237,1305 'print':272,331,416,629,638,919 'privat':431,551,561,565,569 'process':879 'progress':580 'project':152 'punctuat':923 'recogn':20,377,390,395,413,433,553,706,765,1010,1017,1408 'recognit':3,34,44,97,103,109,115,405,418,458,614,639,687,750,754,798,814,864,935,1019,1050,1060,1110,1162,1171,1188,1217,1282,1297,1343,1404 'recognitionrequest':567,674,676 'recognitionrequest.endaudio':1299 'recognitiontask':571,582,584,616,678,680,1233,1255,1257,1259,1306 'recognitiontim':1203 'recognizer.delegate':438,1033 'recognizer.isavailable':414,708 'recognizer.recognitiontask':617,725,849,889,1062,1086,1234,1260 'recognizer.supportsondevicerecognition':784,1143 'record':23,50,94,100,450,594,684,984,1304 'recordbutton.isenabled':1042 'recordingformat':650,660 'refer':131,132,1361 'remov':1295 'repeat':1207 'replac':148 'request':200,357,455,605,607,612,619,713,727,786,842,851,891,928,943,952,962,980,1064,1088,1127,1236,1262,1279 'request.addspunctuation':930 'request.append':663 'request.contextualstrings':945 'request.downloadandinstall':208 'request.requiresondevicerecognition':788,1129,1144 'request.shouldreportpartialresults':609,717,844 'requestpermiss':479 'requestrecordpermiss':517,994 'requir':1138,1318 'requiresondevicerecognit':367 'resourc':1077,1085 'restart':1187,1199 'restartrecognit':1213 'result':117,120,159,260,265,328,540,620,625,728,740,835,839,852,857,872,892,897,1065,1069,1089,1093,1324,1331 'result.besttranscription':904 'result.besttranscription.formattedstring':628,744,869,882 'result.isfinal':633,741,861 'result.text.characters':271,333 'result.transcriptions':914 'return':185,421,492,498,521,523,719,743,859,899,992,1000 'review':126,129,1263 'review-checklist':128 'run':275,1058,1075,1241 'second':1182 'segment':916 'segment.confidence':921 'segment.substring':920 'self':439,1034,1210,1212 'self.audioengine.inputnode.removetap':1099 'self.audioengine.stop':1098 'self.recognitionrequest':611,1102,1104 'self.startrecording':978,1001 'self.stoptranscribing':634,642 'separ':1327 'server':32,108,114,749,812,1151,1184,1341 'server-bas':31,811,1150,1183,1340 'session':588,1172 'set':1285 'setup':79,82,374 'sfspeechaudiobufferrecognitionrequest':539,568,608,787,843,929,944,1128,1379 'sfspeechrecogn':60,78,81,149,337,339,373,391,396,434,443,554,707,766,1018,1038,1375 'sfspeechrecognitionrequest':1391 'sfspeechrecognitionresult':1387 'sfspeechrecognitiontask':572 'sfspeechrecognizer-setup':80 'sfspeechrecognizer.requestauthorization':488,968,985 'sfspeechrecognizerdeleg':430,1283 'sfspeechurlrecognitionrequest':689,714,1383 'silent':1132 'simultan':1216 'skill' 'skill-speech-recognition' 'sort':907 'sosumi.ai':1365,1369,1373,1377,1381,1385,1389,1393,1397,1406,1414 'sosumi.ai/documentation/speech)':1364 'sosumi.ai/documentation/speech/asking-permission-to-use-speech-recognition)':1405 'sosumi.ai/documentation/speech/assetinventory)':1396 'sosumi.ai/documentation/speech/recognizing-speech-in-live-audio)':1413 'sosumi.ai/documentation/speech/sfspeechaudiobufferrecognitionrequest)':1380 'sosumi.ai/documentation/speech/sfspeechrecognitionrequest)':1392 'sosumi.ai/documentation/speech/sfspeechrecognitionresult)':1388 'sosumi.ai/documentation/speech/sfspeechrecognizer)':1376 'sosumi.ai/documentation/speech/sfspeechurlrecognitionrequest)':1384 'sosumi.ai/documentation/speech/speechanalyzer)':1368 'sosumi.ai/documentation/speech/speechtranscriber)':1372 'source-dpearson2699' 'specif':392,939 'speech':2,5,10,43,57,172,382,417,457,475,545,954,963,1362,1403,1409 'speech-recognit':1 'speechanalyz':42,66,71,75,133,136,169,229,301,318,340,1353,1367 'speechanalyzer-io':74 'speechanalyzer.bestavailableaudioformat':224 'speechdetector':352 'speecherror.unavailable':711 'speechmanag':428 'speechrecogn':441,442,1036,1037 'speechstatus':483,495 'speechtranscrib':165,188,305,351,1371 'speechtranscriber.supportedlocale':181,1357 'standard':529 'start':463,613,1167,1222,1281,1310 'startrecord':1174,1194,1232,1254 'starttranscrib':574 'status':489,493,969,986,989 'stay':1011 'still':1074,1240 'stop':1045,1292 'stoptranscrib':669 'stream':212,541 'string':270,332,703,933 'super.init':437 'support':161,204,760,779,825,1125,1136 'supportsondevicerecognit':827,1314 'swift':155,170,302,380,425,473,543,695,763,840,888,926,941,958,1006,1052,1116,1164,1219 'swiftui':946 'tap':645,1294 'task':240,261,581,615,1218,1225,1238,1247 'term':940 'text':7,53,269,273,627,631 'throw':575,702,710,735 'timer':1197 'timer.scheduledtimer':1204 'tip':794 'topic-accessibility' 'topic-agent-skills' 'topic-ai-coding' 'topic-apple' 'topic-claude-code' 'topic-codex-skills' 'topic-cursor-skills' 'topic-ios' 'topic-ios-development' 'topic-liquid-glass' 'topic-localization' 'topic-mapkit' 'transcrib':4,45,176,187,205,226,231,296,304,322 'transcribefil':697 'transcriber.results':267,330 'transcript':17,87,91,167,465,527,630,863,885,901,912 'transcription.segments':918 'tri':201,206,263,279,288,294,312,326,592,599,666,720 'true':324,601,610,789,845,848,931,1071,1095,1130,1145 'type':345 'ui':448 'unavail':453 'undefin':1242 'updat':447 'url':699,700,715,716 'us':402,560,772 'use':8,12,54,154,688,1195,1274,1352,1402 'user':385,1155 'var':566,570 'via':164,371,1031 'vs':30,107,113,748,837 'wast':1076 'weak':1209 'withcheckedcontinu':485,513 'withcheckedthrowingcontinu':722 'without':1123,1226 'withtimeinterv':1205 'work':757 'xcode':947","prices":[{"id":"0bd289dd-08f3-4957-9843-937c5a80b3e8","listingId":"dffc3578-e656-42de-8836-7c01d6cef3c5","amountUsd":"0","unit":"free","nativeCurrency":null,"nativeAmount":null,"chain":null,"payTo":null,"paymentMethod":"skill-free","isPrimary":true,"details":{"org":"dpearson2699","category":"swift-ios-skills","install_from":"skills.sh"},"createdAt":"2026-04-18T20:34:18.821Z"}],"sources":[{"listingId":"dffc3578-e656-42de-8836-7c01d6cef3c5","source":"github","sourceId":"dpearson2699/swift-ios-skills/speech-recognition","sourceUrl":"https://github.com/dpearson2699/swift-ios-skills/tree/main/skills/speech-recognition","isPrimary":false,"firstSeenAt":"2026-04-18T22:01:17.041Z","lastSeenAt":"2026-05-18T18:53:44.210Z"},{"listingId":"dffc3578-e656-42de-8836-7c01d6cef3c5","source":"skills_sh","sourceId":"dpearson2699/swift-ios-skills/speech-recognition","sourceUrl":"https://skills.sh/dpearson2699/swift-ios-skills/speech-recognition","isPrimary":true,"firstSeenAt":"2026-04-18T20:34:18.821Z","lastSeenAt":"2026-05-07T22:40:33.674Z"}],"details":{"listingId":"dffc3578-e656-42de-8836-7c01d6cef3c5","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"dpearson2699","slug":"speech-recognition","github":{"repo":"dpearson2699/swift-ios-skills","stars":599,"topics":["accessibility","agent-skills","ai-coding","apple","claude-code","codex-skills","cursor-skills","ios","ios-development","liquid-glass","localization","mapkit","networking","storekit","swift","swift-concurrency","swiftdata","swiftui","widgetkit","xcode"],"license":"other","html_url":"https://github.com/dpearson2699/swift-ios-skills","pushed_at":"2026-04-26T21:04:17Z","description":"Agent Skills for iOS 26+, Swift 6.3, SwiftUI, and modern Apple frameworks","skill_md_sha":"c667ce7490f6069ce4514e82c7c4b1fb99f9f719","skill_md_path":"skills/speech-recognition/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/dpearson2699/swift-ios-skills/tree/main/skills/speech-recognition"},"layout":"multi","source":"github","category":"swift-ios-skills","frontmatter":{"name":"speech-recognition","description":"Transcribe speech to text using the Speech framework. Use when implementing live microphone transcription with AVAudioEngine, recognizing pre-recorded audio files, configuring on-device vs server-based recognition, handling authorization flows, or adopting the new SpeechAnalyzer API (iOS 26+) for modern async/await speech-to-text."},"skills_sh_url":"https://skills.sh/dpearson2699/swift-ios-skills/speech-recognition"},"updatedAt":"2026-05-18T18:53:44.210Z"}}