10

I'm studying the Speech Recognition on the iOS, but Every time I call the method [_recognitionRequest endAudio] , it always got an error in recognitionTaskWithRequest: the message is in the bottom.

-(void) stopRecording {
if (_disableSpeechSW == YES) {
    return;
}
if (_isAuthorization == NO) {
    return;
}

NSLog(@"stopRecording");

if ([_audioEngine isRunning]) {
    [_audioEngine stop];
    [_recognitionRequest endAudio];
}

}

-(void) startRecording {
..........
[_speechRecognizer recognitionTaskWithRequest:_recognitionRequest
                   resultHandler:^(SFSpeechRecognitionResult *result,NSError *error){
  if (error != nil ) {
     NSLog(@"%@",[error description]);
  }
  else {
   ..........
  }
}];}

[Utility] +[AFAggregator logDictationFailedWithError:] Error Domain=kAFAssistantErrorDomain Code=203 "Retry" UserInfo={NSLocalizedDescription=Retry, NSUnderlyingError=0x17424c690 {Error Domain=SiriSpeechErrorDomain Code=1 "(null)"}}

CodeBender
  • 35,668
  • 12
  • 125
  • 132
  • Hey @Martylin, you should accept the correct answer so other people with the same problem can see which answer was useful. Please read [this help topic on what to do when someone answers your question](http://stackoverflow.com/help/someone-answers). Please also go through your other questions as none are accepted. – Bart Feb 04 '17 at 11:29
  • 2
    The __Code=203 "Retry"__ is not really an error error. It helps to identify when the recognizer did finish and not detect any result. – Ángel Téllez Nov 09 '18 at 23:05

3 Answers3

8

For more clarification about siri speech limitation see this post: Speech Recognition Limits for iOS 10

Use my function below to stop speech recognization. Hope its works.

-(void)stopRecording{

    dispatch_async(dispatch_get_main_queue(), ^{

        if(audioEngine.isRunning){
            [inputNode removeTapOnBus:0];
            [inputNode reset];
            [audioEngine stop];
            [recognitionRequest endAudio];
            [recognitionTask cancel];
            recognitionTask = nil;
            recognitionRequest = nil;
        }
    });
}
Sandip Patel - SM
  • 3,346
  • 29
  • 27
4

I figured it out that the "endAudio" not allow to call from outside the recognitionTaskWithRequest block, if you directly to call the method "[self stopRecording]" then the block will response the error "kAFAssistantErrorDomain Code=203" immediately.

here is the 4 part in my code with stopRecord

1 and 2 is fine

3 and 4 error  

1.from block → detecedVoice → withVoiceControl → stopRecord → ok

2.from block error → stopRecord → startRecord → ok

3.button tap → stopRecord → kAFAssistantErrorDomain Code=203

4.timer 40s → stopRecord → startRecord → kAFAssistantErrorDomain Code=203

  • 3
    Then what is the alternative if I need to call .endAudio from outside recognitionTaskWithRequest , in viewDidDisappear() for example? – Josh Nov 09 '16 at 10:34
  • Have you tried the original Apple's SpeakToMe sample project? Since it contains the same code, as I can see, it seems like another Apple bug, either in the sample, so we all can produce bugs, or in the framework. – lef Apr 26 '17 at 08:30
3

As someone has indicated that it's not exactly an error even though it's disguised as an error. What really has happened is that the recognition time is longer than 1 minute limit Apple has set for the API and during the one minute limit no word has been recognized.
The solution is to add a timer to stop recognition after a period time of less than 60 seconds:

var timerSST = timerSST = Timer.scheduledTimer(timeInterval: value, target: self, selector: #selector(fire), userInfo: nil, repeats: true)

Start the timer when the view controller starts. When the timer expires, it calls:

@objc func fire()
{
    if(startedSTT) {
        stopRecording()
    }
        // restart it
        DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
            do {
                try self.startRecording()
            } catch let error {
                print("There was a problem starting recording: \(error.localizedDescription)")
            }
        }


}  

Here is an example on how to do stop:

    fileprivate func stopRecording() {
    audioEngine.stop()
    request.endAudio()
    recognitionTask?.cancel()
    //recognitionTask?.finish()
    audioEngine.inputNode.removeTap(onBus: 0);
    audioEngine.inputNode.reset()
    startedSTT = false
}

If Stop is not done properly, you won't be able to restart recording for recognition. Pay attention to lines:

recognitionTask?.cancel() vs .finish  

And reset of inputNode:

audioEngine.inputNode.removeTap(onBus: 0);
audioEngine.inputNode.reset()

Using these techniques, I was able to make continues speech recognition work this way.
Hope it helps!

David

us_david
  • 4,431
  • 35
  • 29
  • Was trying to give a button to change the language. Been banging my head for a while because of an error on reinitialisation. Giving delay of 1 sec fixed it! – Jaswant Singh Jan 13 '22 at 16:42