iOS Распознавание речи cra sh на installTapOnBus - [AVAudioIONodeImpl.mm:911:SetOutputFormat: (format.sampleRate == hwFormat.sampleRate)] - PullRequest
0 голосов
/ 06 февраля 2020

В большинстве случаев, когда я запускаю приложение, аудио и тест распознавания речи работают отлично. Но иногда я запускаю его, и он падает при первом запуске распознавания речи. Похоже, что он набирает обороты и совершает sh несколько запусков подряд, поэтому он немного последовательный, как только он входит в одно из своих «настроений» :)

Распознавание начинается после 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'

I вставили try-catches, чтобы посмотреть, предотвращает ли она эту ошибку и нет. Я также добавил крошечный sleep, который также не имел никакого значения. Так что мне даже не ясно, какой код вызывает это. Если я поставлю точку останова перед кодом removeTapOnBus, он не обработает sh, пока не выполнится эта строка. Если я поставлю точку останова на строке installTapOnBus, она не будет обрабатывать sh до этой строки. И если я ставлю точку останова после кода, он падает. Так что, похоже, этот код.

В любом случае, что я делаю не так или как я могу это отладить?

- (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");
            }
        }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...