看来Google似乎已从Google即时中为第三方应用程序提供了离线语音识别。名为Utter的应用程序正在使用它。
有没有人看到过如何使用此离线语音记录执行简单语音命令的任何实现?您是否仅使用常规的SpeechRecognizer API并自动运行?
看来Google似乎已从Google即时中为第三方应用程序提供了离线语音识别。名为Utter的应用程序正在使用它。
有没有人看到过如何使用此离线语音记录执行简单语音命令的任何实现?您是否仅使用常规的SpeechRecognizer API并自动运行?
Answers:
Google确实在该Search更新中悄悄地启用了离线识别功能,但(到目前为止)SpeechRecognizer类中还没有API或其他可用参数。{请参见本文底部的“编辑”}该功能无需其他编码即可使用,但是用户设备必须正确配置才能开始工作,这就是问题所在,我可以想象为什么会有很多开发人员假设他们“错过了一些东西”。
此外,由于硬件限制,Google限制了某些Jelly Bean设备使用脱机识别。适用于哪个设备的文档尚未记录,实际上没有文档记录,因此为用户配置功能已被证明是反复试验的问题(对于他们而言)。它可以立即起作用-对于那些不起作用的对象,这是我提供给他们的“指南”。
编辑:临时将设备区域设置更改为English UK似乎也可以启动这项功能,以供某些用户使用。
一些用户报告说,在开始工作之前,他们仍然必须重新启动几次,但是他们最终都到了那里,通常是莫名其妙地是触发了什么,触发的关键在Google Search APK内,所以不在公共领域或AOSP的一部分。
据我所知,在决定使用离线还是在线识别之前,Google会测试连接的可用性。如果连接最初是可用的,但在响应之前丢失了,则Google将提供连接错误,它不会退回到离线状态。附带说明一下,如果发出了对网络合成语音的请求,则如果失败,将不会提供任何错误-您将保持沉默。
Google搜索更新未在Google即时中启用任何其他功能,实际上,如果您尝试在没有互联网连接的情况下使用它,则会出错。我提到这一点,是因为我想知道该功能是否会像它看起来那样安静地撤回,因此不应在生产中依赖它。
请注意,如果您打算开始使用SpeechRecognizer类,则存在一个与之相关的主要错误,需要您自己的实现才能处理。
无法明确要求offline = true,使得在不操纵数据连接的情况下无法控制此功能。垃圾。您将收到数百封用户电子邮件,询问您为什么未启用如此简单的功能!
编辑:自API级别23起,已添加一个新参数EXTRA_PREFER_OFFLINE,它似乎确实遵守了Google识别服务。
希望以上内容对您有所帮助。
我想改进指南https://stackoverflow.com/a/17674655/2987828发送给用户的图像。这句话是“对于那些没有的人,这是我提供给他们的'指南'。” 我想改善的地方。
用户应单击以下图像中以蓝色突出显示的四个按钮:
然后,用户可以选择任何所需的语言。下载完成后,他应该断开网络连接,然后单击键盘上的“麦克风”按钮。
它对我有用(android 4.1.2),然后语言识别立即可用,而无需重新启动。我现在可以指示终端仿真器外壳的指令!在华硕的padfone 2上,离线速度比在线速度快两倍。
这些图像已根据cc by-sa 3.0进行了许可,并注明出处stackoverflow.com/a/21329845/2987828; 因此,您可以将这些图片连同此归因一起添加到任何地方。
(这是stackoverflow.com上所有图像和文本的标准策略)
简而言之,我没有实现,但是有解释。
Google并未将离线语音识别功能提供给第三方应用程序。离线识别只能通过键盘访问。Ben Randall(完全开发者!)在Android Police上的一篇文章中解释了他的解决方法:
我已经实现了自己的键盘,并在Google语音输入和用户默认键盘之间切换,该键盘带有不可见的编辑文本字段和透明的Activity以获取输入。脏!
这是唯一的方法,因为脱机语音键入只能由IME或系统应用程序触发(这是我的根本技巧)。其他类型的识别API…并未触发它,只是由于服务器错误而失败。…在解决方法上,我浪费了很多工作!但是至少我已经准备好实施了...
通过离线使用onPartialResults和在线使用onResults,我成功地实现了具有离线功能的语音服务。
通过直接下载文件并将它们手动安装在正确的位置,显然可以手动安装脱机语音识别。我想这只是绕过Google硬件要求的一种方法。但是,就我个人而言,我无需重新启动或执行任何操作,只需更改为英国并再次执行即可。
下面给出工作示例,
MyService.class
public class MyService extends Service implements SpeechDelegate, Speech.stopDueToDelay {
public static SpeechDelegate delegate;
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
//TODO do something useful
try {
if (VERSION.SDK_INT >= VERSION_CODES.KITKAT) {
((AudioManager) Objects.requireNonNull(
getSystemService(Context.AUDIO_SERVICE))).setStreamMute(AudioManager.STREAM_SYSTEM, true);
}
} catch (Exception e) {
e.printStackTrace();
}
Speech.init(this);
delegate = this;
Speech.getInstance().setListener(this);
if (Speech.getInstance().isListening()) {
Speech.getInstance().stopListening();
} else {
System.setProperty("rx.unsafe-disable", "True");
RxPermissions.getInstance(this).request(permission.RECORD_AUDIO).subscribe(granted -> {
if (granted) { // Always true pre-M
try {
Speech.getInstance().stopTextToSpeech();
Speech.getInstance().startListening(null, this);
} catch (SpeechRecognitionNotAvailable exc) {
//showSpeechNotSupportedDialog();
} catch (GoogleVoiceTypingDisabledException exc) {
//showEnableGoogleVoiceTyping();
}
} else {
Toast.makeText(this, R.string.permission_required, Toast.LENGTH_LONG).show();
}
});
}
return Service.START_STICKY;
}
@Override
public IBinder onBind(Intent intent) {
//TODO for communication return IBinder implementation
return null;
}
@Override
public void onStartOfSpeech() {
}
@Override
public void onSpeechRmsChanged(float value) {
}
@Override
public void onSpeechPartialResults(List<String> results) {
for (String partial : results) {
Log.d("Result", partial+"");
}
}
@Override
public void onSpeechResult(String result) {
Log.d("Result", result+"");
if (!TextUtils.isEmpty(result)) {
Toast.makeText(this, result, Toast.LENGTH_SHORT).show();
}
}
@Override
public void onSpecifiedCommandPronounced(String event) {
try {
if (VERSION.SDK_INT >= VERSION_CODES.KITKAT) {
((AudioManager) Objects.requireNonNull(
getSystemService(Context.AUDIO_SERVICE))).setStreamMute(AudioManager.STREAM_SYSTEM, true);
}
} catch (Exception e) {
e.printStackTrace();
}
if (Speech.getInstance().isListening()) {
Speech.getInstance().stopListening();
} else {
RxPermissions.getInstance(this).request(permission.RECORD_AUDIO).subscribe(granted -> {
if (granted) { // Always true pre-M
try {
Speech.getInstance().stopTextToSpeech();
Speech.getInstance().startListening(null, this);
} catch (SpeechRecognitionNotAvailable exc) {
//showSpeechNotSupportedDialog();
} catch (GoogleVoiceTypingDisabledException exc) {
//showEnableGoogleVoiceTyping();
}
} else {
Toast.makeText(this, R.string.permission_required, Toast.LENGTH_LONG).show();
}
});
}
}
@Override
public void onTaskRemoved(Intent rootIntent) {
//Restarting the service if it is removed.
PendingIntent service =
PendingIntent.getService(getApplicationContext(), new Random().nextInt(),
new Intent(getApplicationContext(), MyService.class), PendingIntent.FLAG_ONE_SHOT);
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
assert alarmManager != null;
alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, 1000, service);
super.onTaskRemoved(rootIntent);
}
}
更多细节,
希望这对以后的人有所帮助。