3

As per requirement of the App I am developing, I have to pass multiple audio files to SFSpeechRecognizer and get the transcription in return. I did it in two ways

First Method - Using Recursion (Running correctly, you can skip it if you want)

I have first completed this task by getting transcription one by one. i.e when the SFSpeechRecognitionTask gets completed, the result gets saved and the process runs again through a recursive call.

class Transcription
{
    let url = [URL(fileURLWithPath: "sad")]
    var fileCount = 3
    let totalFiles = 4;

    func getTranscriptionRecursive()
    {
        getTranscriptionOfAudioFile(atURL: url[fileCount], fileCount: fileCount, totalFiles: totalFiles) { (result) in

            if(self.fileCount <= self.totalFiles)
            {
                self.fileCount = self.fileCount+1
                self.getTranscriptionRecursive()
            }
        }
    }

    func getTranscriptionOfAudioFile(atURL url: URL, fileCount: Int, totalFiles: Int, completion: @escaping ((SFSpeechRecognitionResult?)->Void))
    {
        let request = SFSpeechURLRecognitionRequest(url: url)

        request.shouldReportPartialResults = false

        let recognizer = SFSpeechRecognizer(locale: Locale(identifier: "en-US"))

        if (recognizer?.isAvailable)! {

            recognizer?.recognitionTask(with: request) { result, error in
                //error handling
                completion(result)
            }
        }
    }
}

This method worked great but it takes way too much time as each SFSpeechRecognizer request takes time to complete.


Second Method - Using Loop and Background Thread (This one is having the issue)

I tried to create multiple requests and execute them in background at once. For that I created a For Loop till the count of audio files, and in that loop I called the function to create SFSpeechRecognizer Request and task.

for index in 0..<urls.count
        {
        DispatchQueue.global(qos: .background).async {
        self.getTranscriptionOfAudio(atURL: self.urls[index]) { (result, myError, message) in

            //error handling

            //process Results
            }
        }
    }

where as the function to get speech recognition results is

func getTranscriptionOfAudio(atURL audioURL: URL?, completion: @escaping ((SFSpeechRecognitionResult? , Error?, String?)->Void))
    {
    let request = SFSpeechURLRecognitionRequest(url: audioURL!)

    request.shouldReportPartialResults = false

    let recognizer = SFSpeechRecognizer(locale: Locale(identifier: "en-US"))

    if (recognizer?.isAvailable)! {

        recognizer?.recognitionTask(with: request) { result, error in
            //error handling

            completion(results,nil,nil)
        }
    } else {
        completion(nil,nil,"Reognizer could not be initialized");
    }
}

When I run this code, only one task executes and other tasks give this error

+[AFAggregator logDictationFailedWithError:] Error Domain=kAFAssistantErrorDomain Code=209 "(null)"

I searched this error on internet but there is no documentation that contains its details.

It might be due to running SFSpeechRecognitionTask in parallel, but in official Apple documents here they didn't forbid to do so, as we can create SFSpeechRecognitionRequest object separately. We don't use singleton object of SFSpeechRecognizer

let me know if anyone has any idea what is going on and what you suggest me to do.

Talha Ahmad Khan
  • 3,416
  • 5
  • 23
  • 38

0 Answers0