macos - 尽管授权成功,但 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
解决方案
您没有收到回调,因为您的二进制文件没有运行循环。我将从这个不同的问题中得到答复,但答案相同:
大多数 Apple 框架中的回调是通过应用程序的主运行循环传递的。如果您的命令行工具没有运行循环,则它无法接收以这种方式发送的回调。
如果没有运行循环,框架调用回调的唯一方法是在另一个线程上运行它,这可能会导致应用程序出现意想不到的奇怪行为。
您可以通过在结束之前插入此代码来手动抽取运行循环main
:
NSRunLoop* runloop = [NSRunLoop currentRunLoop];
[runloop runUntilDate:[NSDate distantFuture]];
这将阻止您的应用程序退出;您需要更新您的逻辑以了解语音识别何时完成并使用while
循环或其他方式对其进行重组 - 但我假设您的“真实”应用程序中的逻辑与这个玩具示例不同。
消息:
AddInstanceForFactory:没有为 id F8BB1C28-BAE8-11D6-9C31-00039315CD46 HALC_ShellDriverPlugIn::Open 注册工厂:无法获得指向 Open 例程的指针
在您的控制台中出现的那是毫无意义的;这是一些从系统框架中泄露出来的日志语句,你可以忽略它。
最后,为了澄清其他几点:
- 需要在“系统偏好设置”>“Siri”中启用“启用询问 Siri”才能使用语音识别
- 存在一个潜在问题,即设备可能会在您第一次检查时报告“设备识别”不可用,尽管所选语言环境支持
推荐阅读
- azure - 如何使用 Runbook 自动化 azure 登录?
- java - Spring boot unittest 在使用 ClassPathScanningCandidateComponentProvider 时给出 NoClassDefFoundError
- javascript - 面包屑导航功能
- python - 从列表列表创建许多列表
- c# - 不使用 task.ContinueWith() 时是否需要重新分配任务值
- java - 如何在 Java 中从具有透明度的 PNG 创建图像蒙版?
- javascript - 在 HTML 表中显示 Json 表
- snakemake - Snakemake 和 STAR
- android - 动画在启动时崩溃的活动
- django - wagtail 和 elasticsearch 不支持 __icontains?