Hello,
I recently enrolled in the Apple Developer Program and created an App ID with the bundle ID com.echo.eyes.voice.
I am trying to enable Speech Recognition in the App ID capabilities list, but the option does not appear — even after waiting over a week since my membership was activated.
I’ve already:
Confirmed my Apple Developer account is active
Checked the Identifiers section in the Developer portal
Tried editing the App ID, but Speech Recognition is not listed
Contacted both Developer Support and Developer Technical Support (Case #102594089120), but was told to post here for help
My app uses Capacitor + the @capacitor-community/speech-recognition plugin. I need the com.apple.developer.speech-recognition entitlement to appear so I can use native voice input in iOS.
I would really appreciate help from an Apple engineer or anyone who has faced this issue.
Thank you,
— Daniel Colyer
Speech
RSS for tagRecognize spoken words in recorded or live audio using Speech.
Posts under Speech tag
51 Posts
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
Hello, I’ve followed all the steps you recommended and confirmed that the entitlement is correctly added in Xcode, but the provisioning profile still fails. I believe the issue is that my App ID com.echo.eyes.app is missing the com.apple.developer.speech-recognition entitlement on Apple’s end.
Could you please manually add this entitlement to my App ID, or guide me on how to get it attached? I’ve already added it locally and confirmed the error in Xcode is due to it not being in the provisioning profile.
.
When a new application runs on iOS 18.4 simulator and tries to access the Speech Framework, prompting a request for authorisation to use Speech Recognition, the application will crash if the user clicks allow. Same issue in the visionOS 2.4 simulator.
Using Swift 6. Report Identifier: FB17686186
/// Checks speech recognition availability and requests necessary permissions.
@MainActor
func checkAvailabilityAndPermissions() async {
logger.debug("Checking speech recognition availability and permissions...")
// 1. Verify that the speechRecognizer instance exists
guard let recognizer = speechRecognizer else {
logger.error("Speech recognizer is nil - speech recognition won't be available.")
reportError(.configurationError(description: "Speech recognizer could not be created."), context: "checkAvailabilityAndPermissions")
self.isAvailable = false
return
}
// 2. Check recognizer availability (might change at runtime)
if !recognizer.isAvailable {
logger.error("Speech recognizer is not available for the current locale.")
reportError(.configurationError(description: "Speech recognizer not available."), context: "checkAvailabilityAndPermissions")
self.isAvailable = false
return
}
logger.trace("Speech recognizer exists and is available.")
// 3. Request Speech Recognition Authorization
// IMPORTANT: Add `NSSpeechRecognitionUsageDescription` to Info.plist
let speechAuthStatus = SFSpeechRecognizer.authorizationStatus()
logger.debug("Current Speech Recognition authorization status: \(speechAuthStatus.rawValue)")
if speechAuthStatus == .notDetermined {
logger.info("Requesting speech recognition authorization...")
// Use structured concurrency to wait for permission result
let authStatus = await withCheckedContinuation { continuation in
SFSpeechRecognizer.requestAuthorization { status in
continuation.resume(returning: status)
}
}
logger.debug("Received authorization status: \(authStatus.rawValue)")
// Now handle the authorization result
let speechAuthorized = (authStatus == .authorized)
handleAuthorizationStatus(status: authStatus, type: "Speech Recognition")
// If speech is granted, now check microphone
if speechAuthorized {
await checkMicrophonePermission()
}
} else {
// Already determined, just handle it
let speechAuthorized = (speechAuthStatus == .authorized)
handleAuthorizationStatus(status: speechAuthStatus, type: "Speech Recognition")
// If speech is already authorized, check microphone
if speechAuthorized {
await checkMicrophonePermission()
}
}
}
Here is the demo from Apple's site
This issues is specific to iOS 18.
When running this demo, we are getting new text when we have a gap in speaking, the recognitionTask(with:resultHandler:) provides new text which is only spoken after the gap and not the concatenation of old text and the new spoken text.
I know there has been issues with SFSpeechRecognizer in iOS 17+ inside the simulator. Running into issues with speech not being recognised inside the visionOS 2.4 simulator as well (likely because it borrows from iOS frameworks). Just wondering if anyone has any work arounds or advice for this simulator issue. I can't test on device because I don't have an Apple Vision Pro.
Using Swift 6 on Xcode 16.3. Below are the console logs & the code that I am using.
Console Logs
BACKGROUND SPATIAL TAP (hit BackgroundTapPlane)
SpeechToTextManager.startRecording() called
[0x15388a900|InputElement #0|Initialize] Number of channels = 0 in AudioChannelLayout does not match number of channels = 2 in stream format.
iOSSimulatorAudioDevice-22270-1: Abandoning I/O cycle because reconfig pending
iOSSimulatorAudioDevice-22270-1: Abandoning I/O cycle because reconfig pending
iOSSimulatorAudioDevice-22270-1: Abandoning I/O cycle because reconfig pending
iOSSimulatorAudioDevice-22270-1: Abandoning I/O cycle because reconfig pending
iOSSimulatorAudioDevice-22270-1: Abandoning I/O cycle because reconfig pending
iOSSimulatorAudioDevice-22270-1: Abandoning I/O cycle because reconfig pending
SpeechToTextManager.startRecording() completed successfully and recording is active.
GameManager.onTapToggle received. speechToTextManager.isAvailable: true, speechToTextManager.isRecording: true
GameManager received tap toggle callback. Tapped Object: None
BACKGROUND SPATIAL TAP (hit BackgroundTapPlane)
GESTURE MANAGER - User is already recording, stopping recording
SpeechToTextManager.stopRecording() called
GameManager.onTapToggle received. speechToTextManager.isAvailable: true, speechToTextManager.isRecording: false
Audio data size: 134400 bytes
Recognition task error: No speech detected <---
Code
private(set) var isRecording: Bool = false
private var recognitionRequest: SFSpeechAudioBufferRecognitionRequest?
private var recognitionTask: SFSpeechRecognitionTask?
@MainActor
func startRecording() async throws {
logger.debug("SpeechToTextManager.startRecording() called")
guard !isRecording else {
logger.warning("Cannot start recording: Already recording.")
throw AppError.alreadyRecording
}
currentTranscript = ""
processingError = nil
audioBuffer = Data()
isRecording = true
do {
try await configureAudioSession()
try await Task.detached { [weak self] in
guard let self = self else {
throw AppError.internalError(description: "SpeechToTextManager instance deallocated during recording setup.")
}
try await self.audioProcessor.configureAudioEngine()
let (recognizer, request) = try await MainActor.run { () -> (SFSpeechRecognizer, SFSpeechAudioBufferRecognitionRequest) in
guard let result = self.createRecognitionRequest() else {
throw AppError.configurationError(description: "Speech recognition not available or SFSpeechRecognizer initialization failed.")
}
return result
}
await MainActor.run {
self.recognitionRequest = request
}
await MainActor.run {
self.recognitionTask = recognizer.recognitionTask(with: request) { [weak self] result, error in
guard let self = self else { return }
if let error = error {
// WE ENTER INTO THIS BLOCK, ALWAYS
self.logger.error("Recognition task error: \(error.localizedDescription)")
self.processingError = .speechRecognitionError(description: error.localizedDescription)
return
}
. . .
}
}
. . .
}.value
} catch {
. . .
}
}
@MainActor
func stopRecording() {
logger.debug("SpeechToTextManager.stopRecording() called")
guard isRecording else {
logger.debug("Not recording, nothing to do")
return
}
isRecording = false
Task.detached { [weak self] in
guard let self = self else { return }
await self.audioProcessor.stopEngine()
let finalBuffer = await self.audioProcessor.getAudioBuffer()
await MainActor.run {
self.recognitionRequest?.endAudio()
self.recognitionTask?.cancel()
}
. . .
}
}
When a new application runs on VisionOS 2.4 simulator and tries to access the Speech Framework, prompting a request for authorisation to use Speech Recognition, the application freezes.
Using Swift 6.
Report Identifier: FB17666252
@MainActor
func checkAvailabilityAndPermissions() async {
logger.debug("Checking speech recognition availability and permissions...")
// 1. Verify that the speechRecognizer instance exists
guard let recognizer = speechRecognizer else {
logger.error("Speech recognizer is nil - speech recognition won't be available.")
reportError(.configurationError(description: "Speech recognizer could not be created."), context: "checkAvailabilityAndPermissions")
self.isAvailable = false
return
}
// 2. Check recognizer availability (might change at runtime)
if !recognizer.isAvailable {
logger.error("Speech recognizer is not available for the current locale.")
reportError(.configurationError(description: "Speech recognizer not available."), context: "checkAvailabilityAndPermissions")
self.isAvailable = false
return
}
logger.trace("Speech recognizer exists and is available.")
// 3. Request Speech Recognition Authorization
// IMPORTANT: Add `NSSpeechRecognitionUsageDescription` to Info.plist
let speechAuthStatus = SFSpeechRecognizer.authorizationStatus() // FAILS HERE
logger.debug("Current Speech Recognition authorization status: \(speechAuthStatus.rawValue)")
if speechAuthStatus == .notDetermined {
logger.info("Requesting speech recognition authorization...")
// Use structured concurrency to wait for permission result
let authStatus = await withCheckedContinuation { continuation in
SFSpeechRecognizer.requestAuthorization { status in
continuation.resume(returning: status)
}
}
logger.debug("Received authorization status: \(authStatus.rawValue)")
// Now handle the authorization result
let speechAuthorized = (authStatus == .authorized)
handleAuthorizationStatus(status: authStatus, type: "Speech Recognition")
// If speech is granted, now check microphone
if speechAuthorized {
await checkMicrophonePermission()
}
} else {
let speechAuthorized = (speechAuthStatus == .authorized)
handleAuthorizationStatus(status: speechAuthStatus, type: "Speech Recognition")
// If speech is already authorized, check microphone
if speechAuthorized {
await checkMicrophonePermission()
}
}
}
Hey there! I faced issue in iOS 18 and newer when Spotlight search doesn't show my App in results. In older versions it works. Here is my code:
func configureUserActivitity(with id: String, keywords: [String]) {
let activity = NSUserActivity(activityType: id)
activity.contentAttributeSet = self.defaultAttributeSet
activity.isEligibleForSearch = true
activity.keywords = Set(keywords)
activity.becomeCurrent()
self.userActivity = activity
}
I didn't find any reasons why it doesn't work now. Maybe I should report a bug?
I'm able to get text to speech to audio file using the following code for iOS 12 iPhone 8 to create a car file:
audioFile = try AVAudioFile(
forWriting: saveToURL,
settings: pcmBuffer.format.settings,
commonFormat: .pcmFormatInt16,
interleaved: false)
where pcmBuffer.format.settings is:
[AVAudioFileTypeKey: kAudioFileMP3Type,
AVSampleRateKey: 48000,
AVEncoderBitRateKey: 128000,
AVNumberOfChannelsKey: 2,
AVFormatIDKey: kAudioFormatLinearPCM]
However, this code does not work when I run the app in iOS 18 on iPhone 13 Pro Max. The audio file is created, but it doesn't sound right. It has a lot of static and it seems the speech is very low pitch.
Can anyone give me a hint or an answer?
Hope it's okay to post here - I haven't gotten resolution anywhere else. Apple's iOs Live Captions is supposed to translate speech into written text either on the phone (works like a charm!) or via microphone (think meeting in a conference room). Microphone doesn't work anywhere, anytime on a new iPhone 14 purchased November 2024. Anyone out there want to fix this and help a lot of people who have trouble hearing? I'm part of an entire generation that didn't know we were supposed to protect our hearing at concerts and clubs and worse, thought it was cool to snag a spot by the speakers...
I have created an app where you can speak using SFSpeechRecognizer and it will recognize you speech into text, translate it and then return it back using speech synthesis. All locales for SFSpeechRecognizer and switching between them work fine when the app is in the foreground but after I turn off my screen(the app is still running I just turned off the screen) and try to create new recognitionTask it it receives this error inside the recognition task: User denied access to speech recognition. The weird thing about this is it only happens with some languages. The error happens with Croatian or Hungarian locale for speech recognition but doesn't with English or Spanish locale.
Hi all!
I have been working on a web speech recognition service using the Web Speech API. This service is intended to work on smartphones, primarily Chrome on Android and Safari (or WebKit WebView) on iOS.
In my specific use case, I need to set the properties continuous = true and interimResults = true. However, I have noticed that interimResults = true does not always work as expected in WebKit.
I understand that this setting should provide fast, native, on-device speech recognition with isFinal = false. However, at times, the recognition becomes throttled and slow, yielding isFinal = true and switching to cloud-based recognition.
To confirm whether the recognition is cloud-based, I tested it by disabling the internet connection before starting speech recognition. In some cases, recognition fails entirely, which suggests that requiresOnDeviceRecognition = false is being applied. (Reference: SFSpeechRecognitionRequest.requiresOnDeviceRecognition)
I believe this is not the expected behavior when setting interimResults = true. I have researched the native services used by the Web Speech API on iOS devices, and the following links seem relevant:
• SFSpeechRecognizer
• SFSpeechRecognitionRequest.shouldReportPartialResults
• SFSpeechRecognizer.supportsOnDeviceRecognition
• Recognizing speech in live audio
• Apple Developer Forums Discussion
I found that setRequiresOnDeviceRecognition and setShouldReportPartialResults appear to be set correctly, but apparently, they do not work as expected:
WebKit Source Code