Google이 타사 앱에 대해 Google Now에서 오프라인 음성 인식을 사용할 수 있도록 한 것 같습니다. Utter라는 앱 에서 사용 중 입니다.
이 오프라인 음성 녹음으로 간단한 음성 명령을 수행하는 방법에 대한 구현을 본 사람이 있습니까? 일반 SpeechRecognizer API를 사용하면 자동으로 작동하나요?
답변:
Google은 해당 검색 업데이트에서 오프라인 인식을 조용히 활성화했지만 아직 SpeechRecognizer 클래스 내에서 사용할 수있는 API 또는 추가 매개 변수가 없습니다 . {이 게시물 하단의 편집 참조} 이 기능은 추가 코딩없이 사용할 수 있지만 작동을 시작하려면 사용자의 장치를 올바르게 구성해야하며 여기에 문제가 있으며 많은 개발자가 왜 많은지 상상할 수 있습니다. 그들이 '뭔가 빠졌다'고 가정합니다.
또한 Google은 하드웨어 제약으로 인해 특정 Jelly Bean 기기에서 오프라인 인식을 사용하지 못하도록 제한했습니다. 이것이 적용되는 장치는 문서화되어 있지 않으며 실제로 문서화되어 있지 않으므로 사용자를위한 기능 구성은 시행 착오의 문제임이 입증되었습니다. 그것은 곧바로 효과가 있습니다 – 그렇지 않은 사람들에게는 이것이 제가 그들에게 제공하는 '가이드'입니다.
편집 : 일시적으로 장치 로케일을 영어 영국으로 변경하면 일부에서 작동하는 것으로 보입니다.
일부 사용자는 여전히 작동을 시작하기 전에 여러 번 재부팅해야한다고보고했지만 결국에는 모두 도달합니다. 종종 트리거가 무엇인지, Google 검색 APK 내부에있는 키에 대해 설명 할 수없는 경우가 많으 므로 공개 도메인이 아닙니다. 또는 AOSP의 일부입니다 .
내가 설정할 수있는 한, Google은 오프라인 또는 온라인 인식 사용 여부를 결정하기 전에 연결 가용성을 테스트합니다. 처음에 연결을 사용할 수 있지만 응답 전에 연결이 끊어진 경우 Google은 연결 오류를 제공하고 오프라인으로 대체하지 않습니다. 부수적으로, 네트워크 합성 음성에 대한 요청이 있으면 실패해도 오류가 제공되지 않습니다.-당신은 침묵을 얻습니다.
Google 검색 업데이트는 Google Now의 추가 기능을 활성화하지 않았으며 실제로 인터넷 연결없이 사용하려고하면 오류가 발생합니다. 나는 그 능력이 보이는 것처럼 조용히 철회 될 것이기 때문에 생산에 의존해서는 안 될지 궁금해서 이것을 언급했습니다.
SpeechRecognizer 클래스 사용을 시작하려는 경우 관련하여 처리하기 위해 자체 구현이 필요한 매우 중요한 버그 가 있다는 점에주의하십시오.
특별히 offline = true를 요청할 수 없기 때문에 데이터 연결을 조작하지 않고는이 기능을 제어 할 수 없습니다. 쓰레기. 그렇게 간단한 것을 활성화하지 않은 이유를 묻는 수백 개의 사용자 이메일을 받게됩니다!
수정 : API 레벨 23 이후 Google 인식 서비스가 준수하는 것으로 보이는 EXTRA_PREFER_OFFLINE 새 매개 변수가 추가되었습니다 .
위의 내용이 도움이되기를 바랍니다.
https://stackoverflow.com/a/17674655/2987828 답변 이 이미지와 함께 사용자에게 보내는 가이드를 개선하고 싶습니다 . "그렇지 않은 사람들에게는 이것이 제가 그들에게 제공하는 '가이드'입니다."라는 문장입니다. 개선하고 싶습니다.
사용자는 다음 이미지에서 파란색으로 강조 표시된 4 개의 버튼을 클릭해야합니다.
그런 다음 사용자는 원하는 언어를 선택할 수 있습니다. 다운로드가 완료되면 네트워크 연결을 끊고 키보드의 "마이크"버튼을 클릭해야합니다.
그것은 나를 위해 일했습니다 (android 4.1.2), 그런 다음 재부팅하지 않고 언어 인식이 즉시 작동했습니다. 이제 터미널 에뮬레이터의 쉘에 명령을 지시 할 수 있습니다! 그리고 ASUS의 padfone 2에서 온라인보다 오프라인에서 두 배 더 빠릅니다.
이러한 이미지는 stackoverflow.com/a/21329845/2987828에 속성이 필요한 cc by-sa 3.0에 따라 라이센스가 부여됩니다. 따라서이 속성과 함께이 이미지를 어디에나 추가 할 수 있습니다.
(이것은 stackoverflow.com의 모든 이미지와 텍스트에 대한 표준 정책입니다)
요컨대, 구현이 아니라 설명입니다.
Google은 타사 앱에 오프라인 음성 인식을 제공하지 않았습니다. 오프라인 인식은 키보드를 통해서만 액세스 할 수 있습니다. Ben Randall (utter! 개발자)은 Android Police의 기사에서 해결 방법을 설명합니다.
나는 내 자신의 키보드를 구현했고 Google 보이스 타이핑과 사용자 기본 키보드와 보이지 않는 편집 텍스트 필드와 투명한 활동을 전환하여 입력을 얻었습니다. 더러운 해킹!
오프라인 음성 입력은 IME 또는 시스템 응용 프로그램 (내 루트 해킹)에 의해서만 트리거 될 수 있기 때문에 이것이 유일한 방법 이었습니다. 다른 유형의 인식 API는… 트리거하지 않고 서버 오류로 인해 실패했습니다. … 해결 방법에 많은 작업이 낭비되었습니다! 하지만 적어도 나는 구현할 준비가되어 있었다 ...
오프라인에서는 onPartialResults를 사용하고 온라인에서는 onResults를 사용하여 오프라인 기능으로 음성 서비스를 성공적으로 구현했습니다.
나는 이것을 다루고 있었고 당신의 언어에 대한 오프라인 패키지를 설치해야한다는 것을 알았습니다. 내 언어 설정은 "Español (Estados Unidos)"이지만 해당 언어에 대한 오프라인 패키지가 없어서 모든 네트워크 연결을 끄면 RecognizerIntent에서 Google에 연결할 수 없다는 경고가 표시되고 언어를 다음으로 변경합니다. "영어 (미국)"(이미 오프라인 패키지가 있기 때문에) RecognizerIntent를 시작했습니다.
키 : 언어 설정 == 오프라인 음성 인식기 패키지
아래에 작업 예가 나와 있습니다.
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);
}
}
상세 사항은,
이것이 미래에 누군가를 도울 수 있기를 바랍니다.