iOS语音识别在installTapOnBus上崩溃-[AVAudioIONodeImpl.mm:911:SetOutputFormat:(format.sampleRate == hwFormat.sampleRate)]

时间:2020-02-06 18:13:48

标签: ios objective-c speech-recognition text-to-speech

大多数情况下,我启动该应用程序时,语音测试语音和语音识别都能完美运行。但是有时我会启动它,并且在第一次启动语音识别时会崩溃。似乎一发不可收拾,连续几次发射都崩溃了,所以一旦进入一种“心情” :)

在TTS引入之后,识别开始,并且TTS说“监听”的同时开始-因此,两者都立即处于活动状态。可能音频需要几毫秒的时间才能转换并崩溃,但是我不清楚这是如何工作或如何防止的。

我看到以下错误:

[avae] AVAEInternal.h:70:_AVAE_Check: required condition is false: 
[AVAudioIONodeImpl.mm:911:SetOutputFormat: (format.sampleRate == hwFormat.sampleRate)]
*** Terminating app due to uncaught exception 'com.apple.coreaudio.avfaudio', 
reason: 'required condition is false: format.sampleRate == hwFormat.sampleRate'

我放了一些try-catches,只是看它是否可以防止该错误,而不能。我还添加了一个很小的sleep,也没有任何区别。所以我什至不知道是哪个代码引起的。如果我在removeTapOnBus代码之前放置一个断点,则在执行此行之前它不会崩溃。如果我将断点放在installTapOnBus行,它直到那行才崩溃。如果我在代码后加上断点,它就会崩溃。因此,似乎确实是这段代码。

无论如何,我在做错什么或如何调试?

- (void) recordAndRecognizeWithLang:(NSString *) lang
    {
        NSLocale *locale = [[NSLocale alloc] initWithLocaleIdentifier:lang];
        self.sfSpeechRecognizer = [[SFSpeechRecognizer alloc] initWithLocale:locale];
        if (!self.sfSpeechRecognizer) {
            [self sendErrorWithMessage:@"The language is not supported" andCode:7];
        } else {

            // Cancel the previous task if it's running.
            if ( self.recognitionTask ) {
                [self.recognitionTask cancel];
                self.recognitionTask = nil;
            }

            //[self initAudioSession];

            self.recognitionRequest = [[SFSpeechAudioBufferRecognitionRequest alloc] init];
            self.recognitionRequest.shouldReportPartialResults = [[self.command argumentAtIndex:1] boolValue];

            // https://developer.apple.com/documentation/speech/sfspeechrecognizerdelegate
            // only callback is availabilityDidChange
            self.sfSpeechRecognizer.delegate = self;      

            self.recognitionTask = [self.sfSpeechRecognizer recognitionTaskWithRequest:self.recognitionRequest resultHandler:^(SFSpeechRecognitionResult *result, NSError *error) {
                NSLog(@"recognise");

                if (error) {
                    NSLog(@"error %ld", error.code);
                    // code 1 or 203 or 216 = we called abort via self.recognitionTask cancel
                    // 1101 is thrown when in simulator
                    // 1700 is when not given permission
                    if (error.code==203){   //|| error.code==216
                        // nothing, carry on, this is bullshit, or maybe not...
                        [self sendErrorWithMessage:@"sfSpeechRecognizer Error" andCode:error.code];
                    }else{
                        [self stopAndRelease];
                        // note: we can't send error back to js as I found it crashes (when recognising, then switch apps, then come back)
                        [self sendErrorWithMessage:@"sfSpeechRecognizer Error" andCode:error.code];
                        return;
                    }
                }

                if (result) {
                    NSMutableArray * alternatives = [[NSMutableArray alloc] init];
                    int maxAlternatives = [[self.command argumentAtIndex:2] intValue];
                    for ( SFTranscription *transcription in result.transcriptions ) {
                        if (alternatives.count < maxAlternatives) {
                            float confMed = 0;
                            for ( SFTranscriptionSegment *transcriptionSegment in transcription.segments ) {
                                //NSLog(@"transcriptionSegment.confidence %f", transcriptionSegment.confidence);
                                if (transcriptionSegment.confidence){
                                    confMed +=transcriptionSegment.confidence;
                                }
                            }
                            NSLog(@"transcriptionSegment.transcript %@", transcription.formattedString);

                            NSMutableDictionary * resultDict = [[NSMutableDictionary alloc]init];
                            [resultDict setValue:transcription.formattedString forKey:@"transcript"];
                            [resultDict setValue:[NSNumber numberWithBool:result.isFinal] forKey:@"final"];
                            float conf = 0;
                            if (confMed && transcription.segments && transcription.segments.count && transcription.segments.count>0){
                                conf = confMed/transcription.segments.count;
                            }
                            [resultDict setValue:[NSNumber numberWithFloat:conf]forKey:@"confidence"];
                            [alternatives addObject:resultDict];
                        }
                    }
                    [self sendResults:@[alternatives]];
                    if ( result.isFinal ) {
                        //NSLog(@"recog: isFinal");
                        [self stopAndRelease];
                    }
                }
            }];

            //[self.audioEngine.inputNode disconnectNodeInput:0];
            AVAudioFormat *recordingFormat = [self.audioEngine.inputNode outputFormatForBus:0];
            //AVAudioFormat *recordingFormat = [[AVAudioFormat alloc] initStandardFormatWithSampleRate:44100 channels:1];
            NSLog(@"samplerate=%f", recordingFormat.sampleRate);
            NSLog(@"channelCount=%i", recordingFormat.channelCount);

            // tried this but does not prevent crashing
            //if (recordingFormat.sampleRate <= 0) {
            //    [self.audioEngine.inputNode reset];
            //    recordingFormat = [[self.audioEngine inputNode] outputFormatForBus:0];
            //}

            sleep(1);  // to prevent random crashes
            @try {
                [self.audioEngine.inputNode removeTapOnBus:0];
            } @catch (NSException *exception) {
                NSLog(@"removeTapOnBus exception");
            }

            sleep(1);  // to prevent random crashes
            @try {
                NSLog(@"install tap on bus");
                [self.audioEngine.inputNode installTapOnBus:0 bufferSize:1024 format:recordingFormat block:^(AVAudioPCMBuffer * _Nonnull buffer, AVAudioTime * _Nonnull when) {
                    //NSLog(@"tap");
                    [self.recognitionRequest appendAudioPCMBuffer:buffer];
                }];
            } @catch (NSException *exception) {
                NSLog(@"installTapOnBus exception");
            }

            sleep(1);  // to prevent random crashes
            [self.audioEngine prepare];
            NSError* error = nil;
            BOOL isOK = [self.audioEngine startAndReturnError:&error];
            if (!isOK){
                NSLog(@"audioEngine startAndReturnError returned false");
            }
            if (error){
                NSLog(@"audioEngine startAndReturnError error");
            }
        }

0 个答案:

没有答案
相关问题