首页 > 解决方案 > 尽管授权成功,但 MacOS 上的 SFSpeechRecognizer 不可用

问题描述

我正在尝试获取一个笨拙的 Objective-C 概念验证示例,以便在 Catalina 上使用 SFSpeechRecognizer 运行,并转录本地音频文件。

经过一番谷歌搜索后,我设法通过添加一个带有 NSSpeechRecognitionUsageDescription 的 Info.plist 来获得授权,并且我得到了授权对话框和正确的 SFSpeechRecognizerAuthorizationStatus (SFSpeechRecognizerAuthorizationStatusAuthorized)。

但是,我的 SFSpeechRecognizer 实例仍然不可用。我怀疑,由于缺乏基本的Objective-C知识,我一定犯了一个愚蠢的错误。

任何提示都非常感谢。

这是我的代码:

//
//  main.m
//  SpeechTestCatalina
//

#import <Foundation/Foundation.h>
#import <Speech/Speech.h>

void transcribeTestFile(){
    NSLocale *locale =[[NSLocale alloc] initWithLocaleIdentifier:@"en-US"];
    SFSpeechRecognizer *speechRecognizer = [[SFSpeechRecognizer alloc] initWithLocale:locale];

    NSLog(@"Locale %@, %@", speechRecognizer.locale.languageCode, speechRecognizer.locale.countryCode);
    NSLog(@"Available %hhd", speechRecognizer.available);
    NSLog(@"Auth status %ld", [SFSpeechRecognizer authorizationStatus]);
    NSLog(@"Supports on device %hhd", speechRecognizer.supportsOnDeviceRecognition);
    if(speechRecognizer.isAvailable && speechRecognizer.supportsOnDeviceRecognition){
        NSString *audioFilePath = @"/Users/doe/speech-detection/speech_sample.wav";
        NSURL *url = [[NSURL alloc] initFileURLWithPath:audioFilePath];
        NSLog(@"Analyzing %@ in language %@", url, locale.languageCode);
        SFSpeechURLRecognitionRequest *urlRequest = [[SFSpeechURLRecognitionRequest alloc] initWithURL:url];
        urlRequest.requiresOnDeviceRecognition = true;
        urlRequest.shouldReportPartialResults = YES; // YES if animate writting
        [speechRecognizer recognitionTaskWithRequest: urlRequest resultHandler:  ^(SFSpeechRecognitionResult * _Nullable result, NSError * _Nullable error){
            NSString *transcriptText = result.bestTranscription.formattedString;
            if(!error){
                NSLog(@"Transcript: %@", transcriptText);
            } else {
                NSLog(@"Error: %@", error);
            }
        }];
    } else {
        NSLog(@"speechRecognizer is not available on this device");
    }
}


int main(int argc, const char * argv[]) {
    @autoreleasepool {
        [SFSpeechRecognizer requestAuthorization:^(SFSpeechRecognizerAuthorizationStatus authStatus) {
            NSLog(@"Status: %ld", (long)authStatus);
            switch (authStatus) {
                case SFSpeechRecognizerAuthorizationStatusAuthorized:
                    //User gave access to speech recognition
                    NSLog(@"Authorized");

                    transcribeTestFile();

                    break;

                case SFSpeechRecognizerAuthorizationStatusDenied:
                    //User denied access to speech recognition
                    NSLog(@"SFSpeechRecognizerAuthorizationStatusDenied");
                    break;

                case SFSpeechRecognizerAuthorizationStatusRestricted:
                    //Speech recognition restricted on this device
                    NSLog(@"SFSpeechRecognizerAuthorizationStatusRestricted");
                    break;

                case SFSpeechRecognizerAuthorizationStatusNotDetermined:
                    //Speech recognition not yet authorized

                    break;

                default:
                    NSLog(@"Default");
                    break;
            }
        }];

        NSLog(@"Sleeping");
        [NSThread sleepForTimeInterval:20.0f];

    }
    return 0;
}

我运行它时的输出是:

2020-01-26 17:48:39.454809+0100 SpeechTestCatalina[3623:82404] Sleeping
2020-01-26 17:48:41.182459+0100 SpeechTestCatalina[3623:82811] Status: 3
2020-01-26 17:48:41.182562+0100 SpeechTestCatalina[3623:82811] Authorized
2020-01-26 17:48:41.186933+0100 SpeechTestCatalina[3623:82811] Locale en, US
2020-01-26 17:48:41.190973+0100 SpeechTestCatalina[3623:82811] Available 0
2020-01-26 17:48:41.191269+0100 SpeechTestCatalina[3623:82811] Auth status 3
2020-01-26 17:48:41.197965+0100 SpeechTestCatalina[3623:82811] Supports on device 0
2020-01-26 17:48:41.198065+0100 SpeechTestCatalina[3623:82811] speechRecognizer is not available on this device
Program ended with exit code: 0

标签: macosspeech-recognitionsfspeechrecognizer

解决方案


您没有收到回调,因为您的二进制文件没有运行循环。我将从这个不同的问题中得到答复,但答案相同

大多数 Apple 框架中的回调是通过应用程序的主运行循环传递的。如果您的命令行工具没有运行循环,则它无法接收以这种方式发送的回调。

如果没有运行循环,框架调用回调的唯一方法是在另一个线程上运行它,这可能会导致应用程序出现意想不到的奇怪行为。

您可以通过在结束之前插入此代码来手动抽取运行循环main

NSRunLoop* runloop = [NSRunLoop currentRunLoop];
[runloop runUntilDate:[NSDate distantFuture]];

这将阻止您的应用程序退出;您需要更新您的逻辑以了解语音识别何时完成并使用while循环或其他方式对其进行重组 - 但我假设您的“真实”应用程序中的逻辑与这个玩具示例不同。


消息:

AddInstanceForFactory:没有为 id F8BB1C28-BAE8-11D6-9C31-00039315CD46 HALC_ShellDriverPlugIn::Open 注册工厂:无法获得指向 Open 例程的指针

在您的控制台中出现的那是毫无意义的;这是一些从系统框架中泄露出来的日志语句,你可以忽略它。


最后,为了澄清其他几点:

  • 需要在“系统偏好设置”>“Siri”中启用“启用询问 Siri”才能使用语音识别
  • 存在一个潜在问题,即设备可能会在您第一次检查时报告“设备识别”不可用,尽管所选语言环境支持

推荐阅读