Возможно ли сделать SpeechRecognizer быстрее?
Я разрабатываю приложение, которое использует Android SpeechRecognizer. Я использую это для чего-то простого. Я нажимаю кнопку, мой SpeechRecognizer начинает слушать, и я получил некоторые результаты из того, что я сказал.
Легко ли? Ну, моя проблема в том, что мне нужно сделать SpeechRecognizer быстрым. Я имею в виду, я нажимаю на кнопку, говорю "Hello", и SpeechRecognizer занимает 3-4 секунды, возвращая массив с возможными результатами. Мой вопрос:
Возможно ли заставить SpeechRecognizer возвращать результаты быстрее? Или занимает меньше времени, чтобы закрыть намерение прослушивания и начать обрабатывать то, что слушает? Может быть, другой способ сделать это? которая будет иметь лучшую производительность, чем эта?
Я проверял библиотеку и увидел 3 параметра:
EXTRA_SPEECH_INPUT_MINIMUM_LENGTH_MILLIS:
Время, которое должно пройти после того, как мы прекратим слышать речь, чтобы считать ввод завершенным.
EXTRA_SPEECH_INPUT_COMPLETE_SILENCE_LENGTH_MILLIS
Минимальная длина высказывания.
EXTRA_SPEECH_INPUT_POSSIBLY_COMPLETE_SILENCE_LENGTH_MILLIS
Время, которое должно пройти после того, как мы прекратим слышать речь, чтобы считать ввод, возможно, завершенным.
http://developer.android.com/intl/es/reference/android/speech/RecognizerIntent.html
Я перепробовал их все, но это не работает, или, может быть, я не использую их. Вот мой код:
public class MainActivity extends Activity {
private static final String TIME_FORMAT = "%02d:%02d:%02d";
private final String TAG = "MainActivity";
private StartTimerButton mSpeakButton;
private CircleProgressBar mCountdownProgressBar;
private CountDownTimer mCountDownTimer;
private TextView mTimer;
private int mRunSeconds = 0;
private SpeechRecognizer mSpeechRecognizer;
private Intent mSpeechRecognizerIntent;
private boolean mIsListening = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mRunSeconds = 0;
mTimer = (TextView) findViewById(R.id.timerText);
mCountdownProgressBar = (CircleProgressBar) findViewById(R.id.progressBar);
mSpeechRecognizer = SpeechRecognizer.createSpeechRecognizer(this);
mSpeechRecognizerIntent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
mSpeechRecognizerIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,
RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
mSpeechRecognizerIntent.putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE,
this.getPackageName());
// mSpeechRecognizerIntent.putExtra(RecognizerIntent.EXTRA_SPEECH_INPUT_MINIMUM_LENGTH_MILLIS,
// 1000);
// mSpeechRecognizerIntent.putExtra(RecognizerIntent.EXTRA_SPEECH_INPUT_COMPLETE_SILENCE_LENGTH_MILLIS,
// 1000);
// mSpeechRecognizerIntent.putExtra(RecognizerIntent.EXTRA_SPEECH_INPUT_POSSIBLY_COMPLETE_SILENCE_LENGTH_MILLIS,
// 1000);
SpeechRecognitionListener listener = new SpeechRecognitionListener();
mSpeechRecognizer.setRecognitionListener(listener);
mSpeakButton = (StartTimerButton) findViewById(R.id.btnSpeak);
mSpeakButton.setReadyState(false);
mSpeakButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mSpeakButton.isReady()) {
if (!mIsListening)
mSpeechRecognizer.startListening(mSpeechRecognizerIntent);
} else
mSpeakButton.setReadyState(true);
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
return true;
}
public void onSpeechResults(ArrayList<String> matches) {
for (String match : matches) {
match = match.toLowerCase();
Log.d(TAG, "Got speech: " + match);
if (match.contains("go")) {
//Do Something
mSpeechRecognizer.stopListening();
}
if (match.contains("stop")) {
//Do Something
mSpeechRecognizer.stopListening();
}
}
}
protected class SpeechRecognitionListener implements RecognitionListener
{
@Override
public void onBeginningOfSpeech()
{
//Log.d(TAG, "onBeginingOfSpeech");
}
@Override
public void onBufferReceived(byte[] buffer)
{
}
@Override
public void onEndOfSpeech()
{
//Log.d(TAG, "onEndOfSpeech");
}
@Override
public void onError(int error)
{
mSpeechRecognizer.startListening(mSpeechRecognizerIntent);
//Log.d(TAG, "error = " + error);
}
@Override
public void onEvent(int eventType, Bundle params)
{
}
@Override
public void onPartialResults(Bundle partialResults)
{
ArrayList<String> matches = partialResults.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION);
for (String match : matches) {
match = match.toLowerCase();
Log.d(TAG, "onPartialResults : " + match);
}
}
@Override
public void onReadyForSpeech(Bundle params)
{
Log.d(TAG, "onReadyForSpeech"); //$NON-NLS-1$
}
@Override
public void onResults(Bundle results)
{
//Log.d(TAG, "onResults"); //$NON-NLS-1$
ArrayList<String> matches = results.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION);
onSpeechResults(matches);
// matches are the return values of speech recognition engine
// Use these values for whatever you wish to do
}
@Override
public void onRmsChanged(float rmsdB)
{
}
}}
Спасибо всем за ваше время! Надеюсь, что кто-то может мне немного помочь:P!
1 ответ
Да, можно уменьшить задержку перед выключением....
Вы не можете изменить количество времени, которое Google считает молчанием в конце разговора пользователя. EXTRA_SPEECH_*
параметры, используемые для работы, теперь они, кажется, время от времени работают в лучшем случае или не работают вообще.
Что вы можете сделать, так это использовать частичные результаты, чтобы найти нужные слова или фразы, а затем вручную отключить службу распознавания.
Вот пример того, как это сделать:
public boolean isHelloDetected(@NonNull final Context ctx, @NonNull final Locale loc, @NonNull final Bundle results) {
boolean helloDetected = false;
if (!results.isEmpty()) {
final String hello = ctx.getString(R.string.hello);
final ArrayList<String> partialData = results.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION);
/* handles empty string bug */
if (partialData != null && !partialData.isEmpty()) {
partialData.removeAll(Collections.singleton(""));
if (!partialData.isEmpty()) {
final ListIterator<String> itr = partialData.listIterator();
String vd;
while (itr.hasNext()) {
vd = itr.next().toLowerCase(loc).trim();
if (vd.startsWith(hello)) {
helloDetected = true;
break;
}
}
}
}
if (!helloDetected) {
final ArrayList<String> unstableData = results.getStringArrayList("android.speech.extra.UNSTABLE_TEXT");
/* handles empty string bug */
if (unstableData != null && !unstableData.isEmpty()) {
unstableData.removeAll(Collections.singleton(""));
if (!unstableData.isEmpty()) {
final ListIterator<String> itr = unstableData.listIterator();
String vd;
while (itr.hasNext()) {
vd = itr.next().toLowerCase(loc).trim();
if (vd.startsWith(hello)) {
helloDetected = true;
break;
}
}
}
}
}
}
return helloDetected;
}
Вы будете запускать этот метод каждый раз, когда вы получаете от onPartialResults()
Если true возвращается, вам нужно позвонить stopListening()
в основной теме (вероятно, new Handler(Looper.getMainLooper()).post(...
Имейте в виду, что после выключения распознавателя вы получите последующие и окончательные результаты onResults()
не может содержать "привет". Поскольку это слово может быть классифицировано только как нестабильное.
Вам нужно будет написать дополнительную логику, чтобы предотвратить использование detectHello()
как только привет будет обнаружен (в противном случае вы будете повторно звонить stopListening()
) - некоторые простые логические маркеры могут решить эту проблему.
Наконец, использование Collections.singleton("")
удаление пустых строк является частью внутреннего отчета об ошибках, детали для репликации здесь и использование ListIterator может быть излишним только для вашего образца; достаточно простого цикла for.
Удачи.