AVAudioSession Error with Shared Instance

Viewed 190

I am having some trouble working with the AVAudioEngine and Apple's dictation to record and process external microphone inputs. My code is as follows:

func recognizeAudioStream() {
        let speechRecognizer = SFSpeechRecognizer()

        //performs speech recognition on live audio; as audio is captured, call append
        //to request object, call endAudio() to end speech recognition
        var recognitionRequest: SFSpeechAudioBufferRecognitionRequest?

        //determines & edits state of speech recognition task (end, start, cancel, etc)
        var recognitionTask: SFSpeechRecognitionTask?

        let audioEngine = AVAudioEngine()


        func startRecording() throws{

            //cancel previous audio task
            recognitionTask?.cancel()
            recognitionTask = nil

            print("here2")
            //get info from microphone
            let audioSession = AVAudioSession.sharedInstance()
            print("here2-")
            try audioSession.setCategory(.record, mode: .measurement, options: .duckOthers)
            print("here2--")
            try audioSession.setActive(true, options: .notifyOthersOnDeactivation)
            print("here2----")

            print("here2")
            let inputNode = audioEngine.inputNode
            print("here3")

            //audio buffer; takes a continuous input of audio and recognizes speech
            recognitionRequest = SFSpeechAudioBufferRecognitionRequest()
            print("here4")
            //allows device to print results of your speech before you're done talking
            recognitionRequest?.shouldReportPartialResults = true
            print("here5")


            recognitionTask = speechRecognizer!.recognitionTask(with: recognitionRequest!) {result, error in

                var isFinal = false
                
                print("here")
                
                if let result = result{ //if we can let result be the nonoptional version of result, then
                    isFinal = result.isFinal
                    print("Text: \(result.bestTranscription.formattedString)")
                    
                }
                
                if error != nil || result!.isFinal{ //if an error occurs or we're done speaking
                    
                    audioEngine.stop()
                    inputNode.removeTap(onBus: 0)
                    
                    recognitionTask = nil
                    recognitionRequest = nil

                    let bufferText = result?.bestTranscription.formattedString.components(separatedBy: (" "))
                    print("completed buffer")
                    
                    self.addToDictionary(wordNames: bufferText)
                    self.populateTempWords()
                    
                    wordsColl.reloadData()
//
                    do{
                        try startRecording()
                    }
                    catch{
                        print(error)
                    }
                    
                }
            
            }
            
            //configure microphone; let the recording format match with that of the bus we are using
            let recordingFormat = inputNode.outputFormat(forBus: 0)
            
            //contents of buffer will be dumped into recognitionRequest and into result, where
            //it will then be transcribed and printed out
            //1024 bytes = dumping "limit": once buffer fills to 1024 bytes, it is appended to recognitionRequest
            inputNode.installTap(onBus: 0, bufferSize: 1024, format: recordingFormat) { (buffer: AVAudioPCMBuffer, when: AVAudioTime) in
                recognitionRequest?.append(buffer)
            }
            
            audioEngine.prepare()
            try audioEngine.start()
        }
        
        do{
            try startRecording()
        }
        catch{
            print(error)
        }
        
        
    }
    

From an entirely inefficient debugging session, I was able to determine that the line let audioSession = AVAudioSession.sharedInstance() produces the first error in the log, while I'm certain the recognitionTask closure produces the second error message:

here2
2021-06-23 22:45:22.707332-0500 DictoCounter[38814:6314709] [plugin] AddInstanceForFactory: No factory registered for id <CFUUID 
here2-
here2--
here2----
here2
here3
here4
here5
2021-06-23 22:45:22.953963-0500 DictoCounter[38814:6314846] [aurioc] 323: Unable to join I/O thread to workgroup ((null)): 2
reg

I should also note that I was able to detect and process audio without errors just a few months ago with this same code, on the same Macbook (and same xcworkspace project). This leads me to believe that it is probably not a code issue, but more of a settings issue.

I did a search prior to posting this question: Swift5 Can't record audio on mac os using AVAudioRecorder ( Error : [plugin] AddInstanceForFactory: No factory registered for id <CFUUID ) seems to indicate the problem is with the info.plist file. However, I've updated it to allow both speech recognition and microphone detection.

enter image description here

Please let me know if you need any more information. Looking forward to solving this problem!

0 Answers
Related