Программист
0,0
рейтинг
21 сентября 2014 в 22:31

Разработка → Сверхбыстрое распознавание речи без серверов на реальном примере tutorial


В этой статье я подробно расскажу и покажу, как правильно и быстро прикрутить распознавание русской речи на движке Pocketsphinx (для iOS порт OpenEars) на реальном Hello World примере управления домашней техникой.
Почему именно домашней техникой? Да потому что благодаря такому примеру можно оценить ту скорость и точность, которой можно добиться при использовании полностью локального распознавания речи без серверов типа Google ASR или Яндекс SpeechKit.
К статье я также прилагаю все исходники программы и саму сборку под Android.



С чего вдруг?


Наткнувшись недавно на статью о прикручивании Яндекс SpeechKit-а к iOS приложению, я задал вопрос автору, почему для своей программы он захотел использовать именно серверное распознавание речи (по моему мнению, это было излишним и приводило к некоторым проблемам). На что получил встречный вопрос о том, не мог бы я поподробней описать применение альтернативных способов для проектов, где нет необходимости распознавать что угодно, а словарь состоит из конечного набора слов. Да еще и с примером практического применения…

Зачем нам что-то еще кроме Яндекса и Google?


В качестве того самого «практического применения» я выбрал тему голосового управления умным домом.
Почему именно такой пример? Потому что на нем можно увидеть те несколько преимуществ полностью локального распознавания речи перед распознаванием с использованием облачных решений. А именно:
  • Скорость — мы не зависим от серверов и поэтому не зависим от их доступности, пропускной способности и т.п. факторов
  • Точность — наш движок работает только с тем словарем, который интересует наше приложение, повышая тем самым качество распознавания
  • Стоимость — нам не придется платить за каждый запрос к серверу
  • Голосовая активация — как дополнительный бонус к первым пунктам — мы можем постоянно «слушать эфир», не тратя при этом свой трафик и не нагружая сервера

Примечание
Сразу оговорюсь, что эти преимущества можно считать преимуществами только для определенного класса проектов, где мы точно заранее знаем, каким словарем и какой грамматикой будет оперировать пользователь. То есть, когда нам не надо распознать произвольный текст (например, СМС сообщение, либо поисковый запрос). В обратном случае без облачного распознавания не обойтись.


Так Android же умеет распознавать речь без интернета!

Да-да… Только на JellyBean. И только с полуметра, не более. И это распознавание — это та же диктовка, только с использованием гораздо меньшей модели. Так что управлять ею и настраивать ее мы тоже не можем. И что она вернет нам в следующий раз — неизвестно. Хотя для СМС-ок в самый раз!

Что будем делать?



Будем реализовывать голосовой пульт управления домашней техникой, который будет работать точно и быстро, с нескольких метров и даже на дешевом тормозном хламе очень недорогих Android смартфонах, планшетах и часах.
Логика будет простой, но очень практичной. Активируем микрофон и произносим одно или несколько названий устройств. Приложение их распознает и включает-выключает их в зависимости от текущего состояния. Либо получает от них состояние и произносит его приятным женским голосом. Например, текущая температура в комнате.

Микрофон будем активировать или голосом, или нажатием на иконку микрофона, или даже просто положив руку на экран. Экран в свою очередь может быть и полностью выключенным.

Вариантов практического применения масса
Утром, не открывая глаз, хлопнули ладонью по экрану смартфона на тумбочке и командуем «Доброе утро!» — запускается скрипт, включается и жужжит кофеварка, раздается приятная музыка, раздвигаются шторы.
Повесим по дешевому (тысячи по 2, не более) смартфону в каждой комнате на стенке. Заходим домой после работы и командуем в пустоту «Умный дом! Свет, телевизор!» — что происходит дальше, думаю, говорить не надо.


На видео показано, что получилось в итоге. Далее же речь пойдет о технической реализации с выдержками из реально работающего кода и немного теории.

Что такое Pocketsphinx



Pocketsphinx — это движок распознавания с открытым исходным кодом под Android. У него также имеется порт под iOS, WindowsPhone, и даже JavaScript.
Он позволит нам запустить распознавание речи прямо на устройстве и при этом настроить его именно под наши задачи. Также он предлагает функцию голосовой активации «из коробки» (см далее).

Мы сможем «скормить» движку распознавания русскую языковую модель (вы можете найти ее в исходниках) и грамматику пользовательских запросов. Это именно то, что будет распознавать наше приложение. Ничего другого оно распознать не сможет. А следовательно, практически никогда не выдаст что-то, чего мы не ожидаем.

Грамматика JSGF
Формат грамматики JSGF используется Pocketsphinx, как и многими другими подобными проектами. В нем можно с достаточной гибкостью описать те варианты фраз, которые будет произносить пользователь. В нашем случае грамматика будет строиться из названий устройств, которые есть в нашей сети, примерно так:
<commands> = лапма | монитор | температура;



Pocketsphinx также может работать по статистической модели языка, что позволяет распознавать спонтанную речь, не описываемую контекстно-свободной грамматикой. Но для нашей задачи это как раз не нужно. Наша грамматика будет состоять только из названий устройств. После процесса распознавания Pocketsphinx вернет нам обычную строчку текста, где устройства будут идти один за другим.

#JSGF V1.0;
grammar commands;
public <command> = <commands>+;
<commands> = лапма | монитор | температура;


Знак плюса обозначает, что пользователь может назвать не одно, а несколько устройств подряд.
Приложение получает список устройств от контроллера умного дома (см далее) и формирует такую грамматику в классе Grammar.

Транскрипции



Грамматика описывает то, что может говорить пользователь. Для того, чтобы Pocketsphinx знал, как он это будет произносить, необходимо для каждого слова из грамматики написать, как оно звучит в соответствующей языковой модели. То есть транскрипцию каждого слова. Это называется словарь.

Транскрипции описываются с помощью специального синтаксиса. Например:
умный  uu m n ay j
дом  d oo m


В принципе, ничего сложного. Двойная гласная в транскрипции обозначает ударение. Двойная согласная — мягкую согласную, за которой идет гласная. Все возможные комбинации для всех звуков русского языка можно найти в самой языковой модели.

Понятно, что заранее описать все транскрипции в нашем приложении мы не можем, потому что мы не знаем заранее тех названий, которые пользователь даст своим устройствам. Поэтому мы будем гененрировать «на лету» такие транскрипции по некоторым правилам русской фонетики. Для этого можно реализовать вот такой класс PhonMapper, который сможет получать на вход строчку и генерировать для нее правильную транскрипцию.

Голосовая активация


Это возможность движка распознавания речи все время «слушать эфир» с целью реакции на заранее заданную фразу (или фразы). При этом все другие звуки и речь будут отбрасываться. Это не то же самое, что описать грамматику и просто включить микрофон. Приводить здесь теорию этой задачи и механику того, как это работает, я не буду. Скажу лишь только, что недавно программисты, работающие над Pocketsphinx, реализовали такую функцию, и теперь она доступна «из коробки» в API.

Одно стоит упомянуть обязательно. Для активационной фразы нужно не только указать транскрипцию, но и подобрать подходящее значение порога чувствительности. Слишком маленькое значение приведет к множеству ложных срабатываний (это когда вы не говорили активационную фразу, а система ее распознает). А слишком высокое — к невосприимчивости. Поэтому данная настройка имеет особую важность. Примерный диапазон значений — от 1e-1 до 1e-40 в зависимости от активационной фразы.

Активация по датчику приближения
Эта задача специфична именно для нашего проекта и напрямую к распознаванию не имеет отношения. Код можно увидеть прямо в главной активности.
Она реализует SensorEventListener и в момент приближения (значение сенсора меньше максимального) включает таймер, проверяя после некоторой задержки, перекрыт ли до сих пор датчик. Это сделано для исключения ложных срабатываний.
Когда датчик снова не перекрыт, мы останавливаем распознавание, получая результат (см описание далее).


Запускаем распознование


Pocketsphinx предоставляет удобный API для конфигурирования и запуска процесса распознавания. Это классы SppechRecognizer и SpeechRecognizerSetup.
Вот как выглядит конфигурация и запуск распознавания:

PhonMapper phonMapper = new PhonMapper(getAssets().open("dict/ru/hotwords"));
Grammar grammar = new Grammar(names, phonMapper);
grammar.addWords(hotword);
DataFiles dataFiles = new DataFiles(getPackageName(), "ru");
File hmmDir = new File(dataFiles.getHmm());
File dict = new File(dataFiles.getDict());
File jsgf = new File(dataFiles.getJsgf());
copyAssets(hmmDir);
saveFile(jsgf, grammar.getJsgf());
saveFile(dict, grammar.getDict());
mRecognizer = SpeechRecognizerSetup.defaultSetup()
    .setAcousticModel(hmmDir)
    .setDictionary(dict)
    .setBoolean("-remove_noise", false)
    .setKeywordThreshold(1e-7f)
    .getRecognizer();
mRecognizer.addKeyphraseSearch(KWS_SEARCH, hotword);
mRecognizer.addGrammarSearch(COMMAND_SEARCH, jsgf);


Здесь мы сперва копируем все необходимые файлы на диск (Pocketpshinx требует наличия на диске аккустической модели, грамматики и словаря с транскрипциями). Затем конфигурируется сам движок распознавания. Указываются пути к файлам модели и словаря, а также некоторые параметры (порог чувствительности для активационной фразы). Далее конфигурируется путь к файлу с грамматикой, а также активационная фраза.

Как видно из этого кода, один движок конфигурируется сразу и для грамматики, и для распознавания активационной фразы. Зачем так делается? Для того, чтобы мы могли быстро переключаться между тем, что в данный момент нужно распознавать. Вот как выглядит запуск процесса распознавания активационной фразы:

mRecognizer.startListening(KWS_SEARCH);

А вот так — распозанвание речи по заданной грамматике:

mRecognizer.startListening(COMMAND_SEARCH, 3000);

Второй аргумент (необязательный) — количество миллисекунд, после которого распознавание будет автоматически завершаться, если никто ничего не говорит.
Как видите, можно использовать только один движок для решения обеих задач.

Как получить результат распознавания


Чтобы получить результат распознавания, нужно также указать слушателя событий, имплементирующего интерфейс RecognitionListener.
У него есть несколько методов, которые вызываются pocketsphinx-ом при наступлении одного из событий:
  • onBeginningOfSpeech — движок услышал какой-то звук, может быть это речь (а может быть и нет)
  • onEndOfSpeech — звук закончился
  • onPartialResult — есть промежуточные результаты распознавания. Для активационной фразы это значит, что она сработала. Аргумент Hypothesis содержит данные о распознавании (строка и score)
  • onResult — конечный результат распознавания. Этот метод будет вызыван после вызова метода stop у SpeechRecognizer. Аргумент Hypothesis содержит данные о распознавании (строка и score)


Реализуя тем или иным способом методы onPartialResult и onResult, можно изменять логику распознавания и получать окончательный результат. Вот как это сделано в случае с нашим приложением:

@Override
public void onEndOfSpeech() {
  Log.d(TAG, "onEndOfSpeech");
  if (mRecognizer.getSearchName().equals(COMMAND_SEARCH)) {
    mRecognizer.stop();
  }
}
@Override
public void onPartialResult(Hypothesis hypothesis) {
  if (hypothesis == null) return;
  String text = hypothesis.getHypstr();
  if (KWS_SEARCH.equals(mRecognizer.getSearchName())) {
    startRecognition();
  } else {
    Log.d(TAG, text);
  }
}
@Override
public void onResult(Hypothesis hypothesis) {
  mMicView.setBackgroundResource(R.drawable.background_big_mic);
  mHandler.removeCallbacks(mStopRecognitionCallback);
  String text = hypothesis != null ? hypothesis.getHypstr() : null;
  Log.d(TAG, "onResult " + text);
  
  if (COMMAND_SEARCH.equals(mRecognizer.getSearchName())) {
    if (text != null) {
      Toast.makeText(this, text, Toast.LENGTH_SHORT).show();
      process(text);
    }
    mRecognizer.startListening(KWS_SEARCH);
  }
}


Когда мы получаем событие onEndOfSpeech, и если при этом мы распознаем команду для выполнения, то необходимо остановить распознавание, после чего сразу будет вызван onResult.
В onResult нужно проверить, что только что было распознано. Если это команда, то нужно запустить ее на выполнение и переключить движок на распознавание активационной фразы.
В onPartialResult нас интересует только распознавание активационной фразы. Если мы его обнаруживаем, то сразу запускаем процесс распознавания команды. Вот как он выглядит:

private synchronized void startRecognition() {
  if (mRecognizer == null || COMMAND_SEARCH.equals(mRecognizer.getSearchName())) return;
  mRecognizer.cancel();
  new ToneGenerator(AudioManager.STREAM_MUSIC, ToneGenerator.MAX_VOLUME).startTone(ToneGenerator.TONE_CDMA_PIP, 200);
  post(400, new Runnable() {
    @Override
    public void run() {
      mMicView.setBackgroundResource(R.drawable.background_big_mic_green);
      mRecognizer.startListening(COMMAND_SEARCH, 3000);
      Log.d(TAG, "Listen commands");
      post(4000, mStopRecognitionCallback);
    }
  });
}

Здесь мы сперва играем небольшой сигнал для оповещения пользователя, что мы его услышали и готовы к его команде. На это время микрофон долже быть выключен. Поэтому мы запускаем распознавание после небольшого таймаута (чуть больше, чем длительность сигнала, чтобы не услышать его эха). Также запускается поток, который остановит распознавание принудительно, если пользователь говорит слишком долго. В данном случае это 3 секунды.

Как превратить распознанную строку в команды


Ну тут все уже специфично для конкретного приложения. В случае с нагим примером, мы просто вытаскиваем из строчки названия устройств, ищем по ним нужное устройство и либо меняем его состояние с помощью HTTP запроса на контроллер умного дома, либо сообщаем его текущее состояние (как в случае с термостатом). Эту логику можно увидеть в классе Controller.

Как синтезировать речь


Синтез речи — это операция, обратная распознаванию. Здесь наоборот — нужно превратить строку текста в речь, чтобы ее услышал пользователь.
В случае с термостатом мы должны заставить наше Android устройство произнести текущую температуру. С помощью API TextToSpeech это сделать довольно просто (спасибо гуглу за прекрасный женский TTS для русского языка):

private void speak(String text) {
  synchronized (mSpeechQueue) {
    mRecognizer.stop();
    mSpeechQueue.add(text);
    HashMap<String, String> params = new HashMap<String, String>(2);
    params.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, UUID.randomUUID().toString());
    params.put(TextToSpeech.Engine.KEY_PARAM_STREAM, String.valueOf(AudioManager.STREAM_MUSIC));
    params.put(TextToSpeech.Engine.KEY_FEATURE_NETWORK_SYNTHESIS, "true");
    mTextToSpeech.speak(text, TextToSpeech.QUEUE_ADD, params);
  }
}


Скажу наверное банальность, но перед процессом синтеза нужно обязательно отключить распознавание. На некоторых устройствах (например, все самсунги) вообще невозсожно одновременно и слушать микрофон, и что-то синтезировать.
Окончание синтеза речи (то есть окончание процесса говорения текста синтезатором) можно отследить в слушателе:

private final TextToSpeech.OnUtteranceCompletedListener mUtteranceCompletedListener = new TextToSpeech.OnUtteranceCompletedListener() {
  @Override
  public void onUtteranceCompleted(String utteranceId) {
    synchronized (mSpeechQueue) {
      mSpeechQueue.poll();
      if (mSpeechQueue.isEmpty()) {
        mRecognizer.startListening(KWS_SEARCH);
      }
     }
  }
};


В нем мы просто проверяем, нет ли еще чего-то в очереди на синтез, и включаем распозанвание активационной фразы, если ничего больше нет.

И это все?


Да! Как видите, быстро и качественно распознать речь прямо на устройстве совсем несложно, благодаря наличию таких замечательных проектов, как Pocketsphinx. Он предоставляет очень удобный API, который можно использовать в решении задач, связанных с распознаванием голосовых команд.

В данном примере мы прикрутили распознавание к вполне кокрентной задаче — голосовому управлению устройствами умного дома. За счет локального распознавания мы добились очень высокой скорости работы и минимизировали ошибки.
Понятно, что тот же код можно использовать и для других задач, связанных с голосом. Это не обязательно должен быть именно умный дом.

Все исходники, а также саму сборку приложения вы можете найти в репозитории на GitHub.
Также на моем канале в YouTube вы можете увидеть некоторые другие реализации голосового управления, и не только системами умных домов.
Дмитрий Че @morfeusys
карма
57,0
рейтинг 0,0
Программист
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама

Самое читаемое Разработка

Комментарии (84)

  • 0
    Спасибо, очень круто, как раз планировал под iOS своему приложению управления умным домом добавить поддержку голоса!
  • 0
    А для чего используется этот контроллер VeraLite?
    • 0
      Так для управления оконечными устройствами. Он формирует сеть ZWave, к которой подключаются устройства. А далее контроллер получает HTTP запросы от приложения и траслирует их в команды ZWave протокола.
  • –6
    «Телефончик, слушай, отправь смсочку Лене и скажи задержусь на пять минут.»

    Голосовое управление станет обыденностью если дивайс сможет распозновать подобные вещи, сказанные бегло и без напряжения.
    • +16
      Статья «немножко» о другом ))
      • –1
        О, заминусили :)

        Я имел ввиду что вы говорите довольно «роботизированным» голосом, с четкими паузами и разделениями слов. Более того, короткими командами. Это не очень практично в обычной жизни, где человек говорит бегло.
        • +16
          Практично? Роботизированным? Дома удобно быстро сказать два-три слова типа «телевизор, кондей, свет на кухне». А не пространными объяснениями типа «уважаемый умный дом, не могли бы вы включить мне...» И далее.
          И чтобы отработало моментально. Я говорю нормальным голосом без особых пауз. Нам нужна четкая голосовая машина, а не «собеседник» типа чатбот. Вот я о таком подходе и рассказал.
    • +4
      Вы не поверите (с)
      Голосовой ассистент Дуся: 4pda.ru/forum/index.php?showtopic=561485 там же есть несколько видеодемонстраций

      К примеру фразы 'Дуся, напиши смску леночке я задержусь на пять минут' или 'Дуся, разбуди меня через три часа' будут распознаны и обработаны как ожидается. Работает offline! так как голосовой движок от google уже работает без интернета, правда чуть медленней чем онлайн вариант.
      • 0
        Почитал эту тему на 4pda —

        Как запустить Дусю из сторонней программы с определенной фразой
        Для этого нужно запустить Broadcast с Action com.dusiassistant.INPUT и в Extras передать строку с именем text

        и подумал, что это же отличный вектор для атаки — фигачим в какую-нибудь говноигрушку «отправь смс на <короткий номер> с текстом ...» и ловим дусеводов…
        • 0
          Угу, при том что Дуся обязательно при этом переспросит голосом владельца, прежде чем что-то отправлять ))
          • 0
            Ну уязвимости то есть ;(
            Пока я игрался с Дусей, обнаружил что при любых включенных механизмах активации на экране блокировки (хоть голосом, хоть потряхиванием, хоть проведением рукой) есть возможность запустить любое приложение (это отключается, как и варианты с навигацией, курсами валют и т.п., реализованные через браузер) сказав 'Открой xxx' например браузер, он будет запущен и позволит с ним работать без снятия блокировки.
            • 0
              Уязвимости? Ээ… Так поставьте графический ключик. Хотя Если ваш телефон в руки взял злоумышленник — то пенять тут на ассистента без толку, ваши данные и без него станут доступны.
              Кстати все виды активации можно вообще выключить. Так что об «уязвимостях» тут говорить неуместно.
              • 0
                Я тестировал именно при блокировки графическим ключом.
                И да, это уязвимость, идеологическая, потому как при закрытии большинства механизмов активации, остается единственный надежный но неудобный — по запуску приложения.
                • 0
                  Есть еще по тапу на виджет. Или с бт гарнитуры. Или из шторки — быстрый старт. У Дуси активаций масса. Читайте внимательнее.
                  Если у вас разблокируется при графическом ключе — то это уже проблемы вашей прошивки.
    • +1
      То, о чем вы пишете, это уже не просто распознавание речи, а интеллектуальный анализ распознанного. Разные вещи.
      • –1
        Вы не поверите, насколько сильно одно связано с другим.
        • 0
          Связано то связано, но вещи разные
        • 0
          Это вещи на стыке разных технологий. Задача процессинга текста по сути никак не связана с распознаванием. Также как и распознавание с процессингом. Но при реализации в единой парадигме можно решать обе задачи более эффективно.
    • 0
      Мимо проходил: wit.ai/
  • 0
    Спасибо за статью!
    Но вера тут никак не обязательна. После распознавания команды можно отправлять запрос на любой контроллер (в моем случае Fibaro).
    • 0
      Да конечно не обязательна. Статья о том, как можно прикрутить такое голосовое управление к чему угодно. У меня есть вера3, к нему и прикрутил. Просто у фибары с верой могут быть разные http протоколы. Пожтому не могу сказать, будет ли работать с фибарой тот же код.
  • 0
    Отличная статья! Спасибо!
  • 0
    Уважаемый автор, подскажите, по нескольким вопросам:
    1. Можно ли использовать данный API не c мобильнымb OS, к примеру с Linux установленным на мини PC.
    2. Какие телефоны из дешевых можно использовать на Android (было что-то сказано против Samsung)?
    3. Можно ли обойтись Vera или аналогом в 1 единственном числе, если у вас дом в несколько этажей и 10 комнат, и к примеру у вас в каждой комнате по 1 дешевому телефону ( как приемник) и как минимум в комнате до 10 устройств (розеток) под управление.
    4. Из 3 вопроса выходит 4 — как локально определять однотипные названия, к примеру жалюзи? Запоминать что в этой комнате есть жалюзи и нужно называть ЖАЛЮЗИ №3 — не удобно. Интересует самоопределение по нахождению с привязкой через конкретный телефон в конкретной комнате.
    5. К примеру я сделал несколько устройств с использованием микроконтроллеров (Arduino с wifi) сам и еще много всего, узкое место — роутер с его пропускной способностью? Сложно ли подружить DIY устройства?
    6. Есть ли оболочка, которая устанавливается на 1 сервер, к которому можно подключиться в графическом режиме через планшет к примеру, указать что куплена новая умная розетка, задать ей имя, указать привязку к конкретному телефону (к примеру телефон № 4 — зал) и по принципу Plug&Play включить за 5 минут?
    • 0
      4. Не ориентируюсь в конкретных контроллерах, но разве нельзя передать вместе с фразой идентификатор телефона дополнительным параметром, и пусть контроллер реагирует соответственно?
    • +1
      Ух как вопросов много. Сразу видно, что вопросом владеете ))
      1. Можно. На сайте pocketsphinx вы можете увидеть один из подобных проектов. Кстати на том же raspberrypi или cubieboard нормально ставится андроид. Придется поэкспериментировать с микрофонами и звуковыми платами.
      2. Да в принципе любые. Ну например мегафон клик, старые htc hero и тп. Насчет самсунга — ничего против. Просто указал, что на них нельзя одновременно и слушать и синтезировать звук. Кстати у самсунгов одни из лучших микрофонов. Даже на самых дешевых моделях.
      3. Ну начнем с того, что умный дом — это далеко не только розетки )) Насчет самой сети zwave — в принципе можно обойтись при особом расчете. Дело в том, что zwave — это самоорганизующаяся сеть, с функцией «черезсеть», т.е. Каждое устройство является ретранслятором радио сигнала. Если правильно расположить устройства так, чтобы каждая пара была в области видимости на несколько метров, то возможно обойтись и одним контроллером. Не будем также забывать о возможности использовать гораздо более дешевые usb контроллеры, подключаемые к пк.
      4. Это уже зависит от логики работы приложения на смартфоне (пульте). Исходники я приложил — можно жкспериментировать )) В одном из проектов мы вообще делали автоматическое определение местоположения андроида по bluetooth маячкам по всему дому — работало хорошо.
      5. Несложно, если вы используете те же протоколы. Но для разношерстных утсройств в одной сети интернета вещей я предлагаю использовать тот же openhab — он может объединить все устройства на более 100 протоколах. Почитайте в моей предыдущей статье.
      6. Это реализовано в тех же контроллерах Vera. Посмотрите мое видео до конца.
    • 0
      Вы сейчас приблизительно описываете то, что я делаю :)
      • 0
        Что конкретно? интересно — давайте пообщаемся
        • 0
          Да, собственно, всё, кроме пункта 5. В качестве контроллера используется обычный ПК с набором донглов.
          Если интересно, то код можно найти у меня в профиле в GitHub. Проект разбит на 3 приложения — ядро системы, веб-интерфейс и терминал на Android.
          Второе и третье в зачаточной стадии, как раз пытаюсь прикрутить сфинкс к андроиду.
  • 0
    Спасибо за ответы! Но вопросом не владею )) как заметили, только только к роботу прикручивать буду голосовые команды и движок выбираю, ранее использовался другой, самопальный. Параллельно и дома хочется что-то сделать умного.
    4. Сама по себе статья про определению местоположения, если возможно, была бы не менее интересна на основе вашего опыта.
    • +1
      Хм… А это можно… Если будет интересно. Это тема про bluetooth low energy (4-я версия).
  • +10
    Я один из соавторов pocketsphinx-android, могу ответить на некоторые вопросы. Есть одна проблема, с которой у всех возникают вопросы, и которая пропущена в этой статье — ресурсы приложения. Суть проблемы в том, что pocketsphinx требует путь, чтобы прочитать файл, а для Android assets возможно получить только InputStream. Поэтому для демонстрационного приложения я написал ant-скрипт, который вычисляет .md5 суммы всех файлов из директории assets/sync и создаёт список, который потом используется для синхронизации файлов между .apk и внешней памятью (обычно, SD-карта). Поэтому, если вы собираете проект через ADT плагин, то убедитесь, что включены соответствующие Ant-шаги в процесс сборки. Впрочем, есть подробное описание, несмотря на существование которого, стабильно раз в неделю кто-нибудь да и напишет в форуме, что у него проблемы с ресурсами.
    • 0
      У меня есть вопрос иного характера.
      Не получится ли так, что подсев на данный движок, со временем он станет платным? Есть такие планы?
      • +3
        Нет, код полностью открытый. Библиотеку можно использовать в коммерческих и закрытых проектах.
    • 0
      Т.е. то что тут лежит в assets не подтягивается pocketsphinx?
      • 0
        Нет, нужно положить в assets/sync и сгенерировать .md5 для каждого файла и контрольный файл со списком ресурсов. В pocketsphinx-android-demo это делается автоматически через ant-скрипт, но вы можете использовать любой способ. Если вы хотите, чтобы все файлы из assets/ синхронизировались, то нужно изменить название директории в pocketsphinx-android.
    • 0
      Не совсем понял. В какой момент времени происходит синхронизация с внешней памятью? И где именно они в итоге лежат? Ни во внутренней памяти, ни на SD карте не нахожу, хотя демонстрационное приложение работает отлично.
      • 0
        Прошу прощения, разобрался в коде примера, вопрос отпал.
    • 0
      Здравствуйте. Я только начинаю разбираться с программированием под android.
      Пример из статьи не заработал, взял пример с сайта библиотеки — заработал, но там только английский язык
      Можете помочь, как добавить в пример с сайта русский для активационной фразы и для распознавания двух команд?
      • 0
        Могу помочь, пишите в личку
  • 0
    А можно ли прикрутить управление телевизором по голосу? телевизор включить, москва24, Громкость плюс 10? По ИК или WiFi(SmartTV)
  • 0
    Холодно у вас дома)
  • 0
    может есть статистика по зависимости ложных срабатываний от количества слов и грамматик?
    • 0
      Грамматики тут не принимают участия. Если вы про активацию голосом. В активации голосом нужно подбирать подходящее значение порога.
      Плюс еще важно, что активационная фраза не должна быть короткой. Примерно 2 слова по 2-3 слога в каждом. Необходимо также очень аккуратно писать транскрипции.
  • 0
    Круто, сейчас тоже прикручиваю. Но с помощью 1 Sheeld и не совсем удачно работает распознование голоса. Какова дальность определение? Думаю пристроить к андройд девайсу микрофон ШОРОХ
  • 0
    У меня был очень негативный опыт работы с pockeysphinx под Ubuntu и ROS. Нужно было распознавание, которое реально совместить с ROS, быстро работающее и не как можно меньше зависящее от внешних условий, дикторонезависимое. Мне так и не удалось настроить pocketsphinx на хорошее распознавание, постоянные ошибки были. После такой оптимистичной статьи попробую еще раз при случае — может, у меня руки не из того места оказались.
    • +1
      Библиотеку такого типа невозможно заставить работать их коробки для абсотютно всех случаев. Есть распознавание гугла — оно работает без настроек. Но вы ничего не контролируете, кроме языка. В конфигурации pocketsphinx есть опция -rawlogdir, она задаёт путь к директории, куда сохраняются записи во время распознавания. Прослушайте записи, возможно, вы записываете не в том формате. Это очень распротранённая ошибка. Если в форматом всё хорошо, то вы можете написать в список рассылки, форум или #cmusphinx на freenode, указав ссылки на записи и вашу конфигурацию. Также, сейчас есть некоторые проблемы с версионностью. По сути, сейчас можно скачать trunk/master или 0.8, и они очень сильно различаются. Я советую скачивать первую версию. Есть не собирается — пишите, такое бывает. Разработчиков немного, но все откликаются оперативно.
  • 0
    Спасибо за статью. Я. правильно понимаю, что можно совместить оба метода и после «условных 3 секунд», если команда не распознана, отправлять запись на серверный движок??
    • 0
      Ну теоретически можно. Но на какой движок и зачем вы будете это отправлять? Тем более если вы что-то сказали, то pocketsphinx все равно вернет вам какую-то гипотезу по грамматике.
  • 0
    Спасибо, появился повод разобраться уже с этой библиотекой. Давно пора прикрутить её к моей Вике.
    • 0
      Да, действительно. Я-то уж давно прикрутил ее к моей Дусе ;-)
      и в умный дом еще
  • 0
    На мой згляд, было бы здорово добавить универсализма, например отправлять результаты через mqtt.
      • 0
        К сожалению видео демонстрация это совсем не «how to».
      • 0
        Кроме того, не OpenHAB ом единым…
      • 0
        Посмотрите все же на протокол mqtt. С его помощью можно с десятками систем интегрироваться. От MySensors до node-red.
        • 0
          Еще раз отвечу вам — openhab. Он интегрирован и с mqtt тоже. Openhab интегрируется с сотней систем, а не с десятком.
          • 0
            Вы имеете ввиду протоколы взаимодействия с оборудованием(z-wave, x10, knx ...), а я про системы домашней автоматизации, такие как openhab, mysensors.
            То есть, написав модуль, взаимодействующий с миром посредством mqtt вы потом без труда можете его подключить к любому продукту с поддержкой mqtt.
            • 0
              Тогда, возвращаясь к вашей реплике
              На мой згляд, было бы здорово добавить универсализма, например отправлять результаты через mqtt.

              Какие результаты вы бы предложили отправлять через mqtt???
              • 0
                Номер слова/выражения из списка(как работает EasyVR) или само слово/выражение.
              • 0
                Если «на той стороне» достаточно умное приложенние, то всю логику, модель языка можно там выстроить.
                • 0
                  Простите, а зачем логика должна быть где-то?? Кокретно в данном приложении логика на клиенте и этого хватает для решения конкретной задачи…
                  • 0
                    У меня в первом приближении получилось так:
                    Дуся распознает Event таскера. Таскер с помощью плагина MQTT Sender отсылает сообщение с топиком, «actions/команда» и телом {'id': номер}
                    Поток в Node-RED слушает соответствующий топик и посылает команду устройству с соответствующим айди.
  • 0
    Вчера наконец-то дошли руки разобраться в этой библиотеке. Сейчас я для умного дома использую онлайновую распознавалку от Google. Надо сказать, что у Pocketsphinx есть как плюсы, так и минусы.

    Минусы:

    • В «grammar-based» режиме фразы распознаются неплохо за счёт того, что используется заранее заданный список, но таким образом иногда и любой шум принимается за какую-то команду.
    • Чтобы не было вышеописанной проблемы, приходится использовать ключевое слово для активации. Как уже сказал автор, оно не должно быть коротким. Это в разы понижает удобство использования, ведь я как-то уже привык, что ночью достаточно сказать просто «открой окно» или «включи компьютер» без всяких прелюдий в виде «умный дом». При этом моё привычное необязательное обращение по имени «Вика» слишком короткое.
    • Всё-таки плохо распознаётся с большого расстояния. Или я что-то плохо настроил? Но пока я тестировал Pocketsphinx, на мои команды гораздо чаще реагировал планшет, который находится в другом конце комнаты и использует распознавание от Google.


    Плюсы:

    • Скорость. Абсолютно мгновенная реакция на команды. В случае с Google приходится ждать лишнюю секунду, а если использовать Android 4.4, то из-за костылей иногда доходит и до пяти секунд.
    • Автономность, не нужен Интернет.


    Пока что минусов для меня больше :(
    • 0
      Первая проблема — не проблема. Решается за счет правильно написанной грамматики (garbage) и фильтрации результат по score, который можно легко посчитать. Это обычная практика для распознавания на базе контекстно-свободной грамматики.
      Второе — «в разы понижает удобство»??? Я как-то не заметил этого «в разы». А вы гуглом все время слушаете эфир на предмет команды?? Ого… Гугл вас забанит или весь трафик съест )) Плюс гугл любит становиться «недоступным» — это все же облачный сервис…
      Третье — еще все зависит от микрофона. Вы говорите что гугл распознает с нескольких метров?? Не поверю. Гугл распознавание рассчитано на небольшое расстояние. А в шуме вы от него вообще не добьетесь результата на расстоянии метра.
      • 0
        Вот пишу файл грамматики, действительно становится лучше.

        Да, постоянно слушаю эфир, но при этом из общего шума вполне неплохо выделяется голос, так что запросы происходят не непрерывно. Никаких проблем.

        В почти полной тишине (шум компьютера) — Google легко распознаёт с нескольких метров. В абсолютно полной тишине берёт и с пяти-семи метров. Правда, так было не всегда. Впечатление, что в последнее время они как-то оптимизировали распознавание. Меня это даже напугало немного. Pocketsphinx шум тоже как-то не очень любит
        • 0
          Шум не любит не покетсфинкс, а я конкретная аккустическая модель. Если натренеровать свою — будет работать и в шуме.
          Если постоянно слушать эфир… Ну что тут сказать — трафик плюс гугл в конечном итоге откажет вашему приложению в обслуживании, как только вашей системой начнете пользоваться не только вы…
          • 0
            У API ключей Гугла вполне себе определённые ограничения по запросам в сутки, за пределы которых я не выхожу.
            • 0
              Ну это только вы )) и сколько же у них ограничения? )) вообще-то под андроидом ограничения нет, но все же — слушать постоянно голос в облаке… это как-то что-то странно… И гугл будет очень недоволен, если это будет делать еще хотя бы пара тысяч человек…
    • 0
      Называй теперь свой дом вместо Вики какой-нибудь Алефтиной и двух проблем сразу не станет)
      А проблему с дистанцией, как мне кажется, можно решить исопльзованием нескольких микрофонов по всей квартире с равномерным покрытием всей площади. От этого все равно никуда не денешься, разве что на себе микрофон носить.
      • 0
        «Окей, Вика» || «Короче, Вика»
  • 0
    Добрый день!

    Подскажите пожалуйста такой вопрос по приведённым исходникам, как поменять ключевую фразу активации?
    Нашёл, что она прописана в strings.xml как «Умный дом», так же в файле hotwords как два слова:
    умный uu m n ay j
    дом d oo m
    пытался менять на свою фразу, но что-то ничего не получилось. нужно ли менять её в обоих местах (в каком-то особенном формате?) или как-то ещё по-другому?

    P.S. может кому-нибудь пригодится — у меня не получалось запустить движок без добавления двух файлов-библиотек в проект:
    libs\armeabi\libpocketsphinx_jni.so
    libs\armeabi-v7a\libpocketsphinx_jni.so
  • 0
    Если в этой статье ещё найдутся живые люди, помогите понять, что есть score?
    • 0
      Рискну предположить, что score это коэффициент похожести распознанного с активационной фразой.
      • 0
        Это я тоже рискнул предположить.
        Score, кстати, указывается не только для активационной фразы, но и для любой распознанной (включая распознанную по грамматике).
        Вот только как с ним правильно работать и от чего конкретно он зависит, это уже более сложный вопрос.
  • 0
    А где реализация getAssets()?
    • 0
      Прошу прощения, разобрался, первый проект под Android )
  • 0
    А что с оффлайн-распознаванием под Windows?
    Был Realspeeker, но сейчас не работает, обещают новую версию.
    Да и работал он онлайн, судя по тому, что сейчас не действуют старые дистрибутивы.

    Был когда-то горыныч, но давно он был так себе.

    Что рекомендуется сейчас для набора текстов?
    • 0
      библиотека собирается под большинство архитектур и операционных систем, windows в их числе
  • 0
    Совсем никак он не распознаёт мой английский, даже если я говорю те же фразы что в демо-файлах (их он распознаёт). При этом я уверен в том, что формат моих записей правильный. В общем, сразу как-то не заладилось.
    • +1
      Сегодня мне ответили на форуме, причина была в том, что алгоритм не успевает адаптироваться к распознаванию коротких фраз. Эту адаптацию надо провести самому, что не должно быть ни долго, ни сложно — по идее, около минуты поговорить надо, извлечь получившиеся коэффициенты и поместить их в конфигурацию.

      • 0
        Спасибо вам! Очень ценное дополнение, у меня тоже были подобные проблемы. Пойду достану проект из шкафчика и попробую еще раз.

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.