Недавно я повторно посетил CMU Sphinx и попытался настроить базовый детектор горячих слов для Android, начиная с учебника и адаптируя пример приложения.
У меня возникают различные проблемы, которые я не смог решить, несмотря на глубокое изучение их документации, пока не могу больше читать...
Чтобы воспроизвести их, я сделал базовый проект, предназначенный для обнаружения ключевых слов разбуди тебя и разбуди меня.
Мой словарь:
me M IY
wakeup W EY K AH P
you Y UW
Моя языковая модель:
\data\
ngram 1=5
ngram 2=5
ngram 3=4
\1-grams:
-0.9031 </s> -0.3010
-0.9031 <s> -0.2430
-1.2041 me -0.2430
-0.9031 wakeup -0.2430
-1.2041 you -0.2430
\2-grams:
-0.3010 <s> wakeup 0.0000
-0.3010 me </s> -0.3010
-0.6021 wakeup me 0.0000
-0.6021 wakeup you 0.0000
-0.3010 you </s> -0.3010
\3-grams:
-0.6021 <s> wakeup me
-0.6021 <s> wakeup you
-0.3010 wakeup me </s>
-0.3010 wakeup you </s>
\end\
Оба вышеперечисленных были созданы с помощью рекомендуемого инструмента.
И мой файл ключевых фраз:
wakeup you /1e-20/
wakeup me /1e-20/
Адаптируя приведенный выше пример приложения, вот мой код:
public class PocketSphinxActivity extends Activity implements RecognitionListener {
private static final String CLS_NAME = PocketSphinxActivity.class.getSimpleName();
private static final String HOTWORD_SEARCH = "hot_words";
private volatile SpeechRecognizer recognizer;
@Override
public void onCreate(Bundle state) {
super.onCreate(state);
setContentView(R.layout.main);
new AsyncTask<Void, Void, Exception>() {
@Override
protected Exception doInBackground(Void... params) {
Log.i(CLS_NAME, "doInBackground");
try {
final File assetsDir = new Assets(PocketSphinxActivity.this).syncAssets();
recognizer = defaultSetup()
.setAcousticModel(new File(assetsDir, "en-us-ptm"))
.setDictionary(new File(assetsDir, "basic.dic"))
.setKeywordThreshold(1e-20f)
.setBoolean("-allphone_ci", true)
.setFloat("-vad_threshold", 3.0)
.getRecognizer();
recognizer.addNgramSearch(HOTWORD_SEARCH, new File(assetsDir, "basic.lm"));
recognizer.addKeywordSearch(HOTWORD_SEARCH, new File(assetsDir, "hotwords.txt"));
recognizer.addListener(PocketSphinxActivity.this);
} catch (final IOException e) {
Log.e(CLS_NAME, "doInBackground IOException");
return e;
}
return null;
}
@Override
protected void onPostExecute(final Exception e) {
Log.i(CLS_NAME, "onPostExecute");
if (e != null) {
e.printStackTrace();
} else {
recognizer.startListening(HOTWORD_SEARCH);
}
}
}.execute();
}
@Override
public void onBeginningOfSpeech() {
Log.i(CLS_NAME, "onBeginningOfSpeech");
}
@Override
public void onPartialResult(final Hypothesis hypothesis) {
Log.i(CLS_NAME, "onPartialResult");
if (hypothesis == null)
return;
final String text = hypothesis.getHypstr();
Log.i(CLS_NAME, "onPartialResult: text: " + text);
}
@Override
public void onResult(final Hypothesis hypothesis) {
// unused
Log.i(CLS_NAME, "onResult");
}
@Override
public void onEndOfSpeech() {
// unused
Log.i(CLS_NAME, "onEndOfSpeech");
}
@Override
public void onError(final Exception e) {
Log.e(CLS_NAME, "onError");
e.printStackTrace();
}
@Override
public void onTimeout() {
Log.i(CLS_NAME, "onTimeout");
}
@Override
public void onDestroy() {
super.onDestroy();
Log.i(CLS_NAME, "onDestroy");
recognizer.cancel();
recognizer.shutdown();
}
}
Примечание. Если я изменю выбранные ключевые фразы (и другие связанные файлы), чтобы они были более непохожими, и протестирую реализацию в тихой обстановке, примененные настройки и пороговые значения будут работать очень успешно.
Проблемы
- Когда я говорю либо разбуди тебя, либо разбуди меня, оба будут обнаружены.
Я не могу установить, как применить повышенный вес к конечным слогам.
- Когда я говорю просто пробуждение, часто (но не всегда) будут обнаружены оба.
Я не могу установить, как я могу избежать этого.
- При тестировании на фоновом шуме ложные срабатывания слишком часты.
Я не могу понизить базовые пороги, которые я использую, иначе ключевые фразы не будут последовательно определяться в нормальных условиях.
- При тестировании на фоновом шуме в течение длительного периода (5 минут должно быть достаточно для воспроизведения) немедленное возвращение в тихую среду и произнесение ключевых фраз не приводит к обнаружению.
Требуется неопределенный период времени, прежде чем ключевые фразы будут успешно и неоднократно обнаружены, как если бы тест начался в тихой обстановке.
Я нашел потенциально связанный вопрос, но ссылки больше не работают. Интересно, не следует ли мне чаще сбрасывать распознаватель, чтобы как-то сбросить фоновый шум от усреднения в пороги обнаружения?
- Наконец, интересно, позволят ли мои требования к ограниченному количеству ключевых фраз уменьшить размер акустической модели?
Любые накладные расходы при упаковке в моем приложении, конечно, будут полезны.
Наконец (честно!), и особенно надеясь, что @NikolayShmyrev заметит этот вопрос, есть ли какие-либо планы по завершению базовая реализация Android / SDK полностью через gradle?
Я благодарю тех, кто зашел так далеко...