Сверхбыстрое распознавание речи без серверов на реальном примере. Лучшая программа распознания русской речи Скачивание пакета данные для распознавания речи офлайн

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

С чего вдруг?

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

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

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

Примечание

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

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

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

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

Вариантов практического применения масса

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

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



Грамматика описывает то, что может говорить пользователь . Для того, чтобы 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
  • 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 params = new HashMap(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, который можно использовать в решении задач, связанных с распознаванием голосовых команд.

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

  • голосовое управление
  • голосовой движок
  • Добавить метки

    Обновлено: Понедельник, Июль 31, 2017

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

    Стало традицией приводить в пример голосового общения человека с ЭВМ какой- либо фантастический фильм, ну хоть бы «Космическая одиссея 2001» режиссера Стэнли Кубрика. Там бортовой компьютер не только ведет осмысленный диалог с астронавтами, но умеет читать по губам как глухой. Другими словами, машина научилась распознавать человеческую речь без ошибок. Возможно, кому-то дистанционное голосовое управление фотокамерой покажется лишним, но многим бы понравилось такая фраза «Сними нас, крошка» и снимок всей семьи на фоне пальмы готов.

    Ну, вот и я отдал дань традиции, слегка пофантазировал. Но, говоря от души, эта статья писалась трудно, а началось все с подарка в виде смартфона с ОС «Андроид 4». Эта модель HUAWEI U8815 имеет небольшой сенсорный экран в четыре дюйма и экранную клавиатуру. Набирать на ней несколько непривычно, но оказалось это и не особенно нужно. (image01)

    1. Распознание голоса в смартфоне на ОС «Андроид»

    Осваивая новую игрушку, я заметил графическое изображение микрофона в строке поиска Google и на клавиатуре в «Заметках». Ранее мне было не интересно, что этот символ обозначает. Разговоры я вел в Skype , а письма набирал на клавиатуре. Так поступает большинство пользователей Интернета. Но как потом мне объяснили, в поисковик Google был добавлен голосовой поиск на русском языке и появились программы, позволяющие диктовать короткие сообщения при использовании браузера «Chrome» .

    Я произнес фразу из трех слов, программа их определила и показала в ячейке с синим фоном. Тут было чему удивиться, потому что все слова были написаны правильно. Если нажать на эту ячейку, то фраза появляется в текстовом поле андроид-блокнота. Так еще пару фраз наговорил и отправил сообщение помощнику по SMS.


    2. Краткая история программ распознания голоса.

    Для меня не было открытием, что современные достижения в области управления голосом позволяют отдавать команды бытовой технике, автомобилю, роботу. Командный режим был представлен в прошлых версиях Windows, OS/2 и Mac OS. Мне встречались программы-говорилки, но что с них пользы? Возможно, это моя особенность, что говорить мне проще, чем печатать на клавиатуре, а на сотовом телефоне я вообще не могу ничего набрать. Приходится записывать контакты на ноутбуке с нормальной клавиатурой и передавать по USB кабелю. Но чтобы просто говорить в микрофон и компьютер сам набирал текст без ошибок – это для меня было мечтой. Атмосферу безнадежности поддерживали дискуссии на форумах. В них везде была такая печальная мысль:

    «Однако на деле до настоящего времени программ для реального распознавания речи (да еще и на русском языке) практически не существует, и созданы они будут, очевидно, не скоро. Более того, даже обратная распознаванию задача - синтез речи, что, казалось бы, значительно проще распознавания, до конца так и не решена». (КомпьютерПресс №12, 2004г.)

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

    При этом обзоры англоязычных программ ввода текста голосом указывали на явные успехи. Например, IBM ViaVoice 98 Executive Edition имела базовый словарь в 64000 слов и возможность добавления такого же количества своих слов. Процент распознания слов без тренировки программы был около 80% и при последующей работе с конкретным пользователем доходил до 95%.

    Из программ распознания русского языка стоит отметить «Горыныч» – дополнение к англоязычной Dragon Dictate 2.5. Про поиски, а потом «битву с пятью Горынычами» я расскажу во второй части обзора. Первым я нашел «английского Дракона».

    3. Программа распознания слитной речи «Dragon Naturally Speaking»

    Современная версия программы фирмы «Nuance» оказалась у моей давнишней знакомой по Минскому институту иностранных языков. Она ее привезла из заграничной поездки, а купила, думая, что та сможет быть «компьютерным секретарем». Но что-то не пошло, и программа осталась на ноутбуке почти забытая. По причине отсутствия сколь-нибудь внятного опыта мне пришлось ехать к своей знакомой самому. Все это длительное вступление необходимо для правильного понимания выводов, которые я сделал.

    Полное название первого моего дракона звучало так: . Программа на английском и все в ней понятно даже без руководства. Первым шагом необходимо создать профиль конкретного пользователя для определения особенностей звучания слов в его исполнении. Что я и сделал – важен возраст говорящего, страна, особенности произношения. Мой выбор таков: возраст 22–54 года, английский UK, произношение стандартное. Далее идет несколько окон, в которых вы настраиваете свой микрофон. (image04)

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

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

    Отказавшись от адаптации программой моего произношения, я перешел в основное окно и запустил встроенный текстовой редактор. Говорил отдельные слова из каких-то текстов, что нашел на компьютере. Те слова, что произнес правильно, программа напечатала, те, что плохо сказал, заменила чем-то «английским». Произнеся команду «стереть строку» по-английски четко – программа ее выполнила. Значит, команды я читаю правильно, и программа распознает их без предварительной тренировки.

    Но мне было важно, как этот «дракон» пишет по-русски. Как вы поняли из предыдущего описания, при тренировке программы можно выбрать только английский текст, русского там попросту нет. Понятно, что и натренировать распознание русской речи не получится. На следующем фото можно увидеть, какую фразу набрала прога при произнесении русского слова «Привет». (image06)

    Итог общения с первым драконом получился слегка комичным. Если внимательно почитать текст на официальном сайте, то можно увидеть английскую «специализацию» этого программного продукта. Кроме того, при загрузке мы читаем в окне программы «English». Так зачем это все было нужно. Понятно, что виноваты форумы и слухи…

    Но есть и полезный опыт. Моя знакомая попросила посмотреть состояние ее ноутбука. Как-то медленно он стал работать. Это не удивительно – системный раздел имел только 5% свободного места. Удаляя ненужные программы я увидел, что официальная версия занимала более 2,3 Гб. Эта цифра нам пригодится позже. (image. 07)



    Распознание русской речи, как оказалось, было задачей нетривиальной. В Минске мне удалось найти у знакомого «Горыныча». Диск он долго искал в своих старых завалах и, по его словам, это официальное издание. Установилась прога мгновенно, и я узнал, что в ее словаре есть 5000 русских слов плюс 100 команд и 600 английских слов плюс 31 команда.

    Вначале нужно настроить микрофон, что я сделал. Потом открыл словарь и добавил слово «проверка» ибо его не оказалось в словаре программы. Старался говорить четко, монотонно. Наконец, открыл программу «Горыныч Про 3,0», включил режим диктовки и получил вот такой список «близких по звучанию слов». (image. 09)

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

    5. Возможности компании Google по работе с голосом

    Для работы с голосом на обычном компьютере с OS Windows вам понадобится установить браузер Google Chrome . Если вы в нем работаете в Интернете, то внизу справа можно нажать на ссылку магазина программного обеспечения. Там совершенно бесплатно я нашел две программы и два расширения для голосового ввода текста. Программы называются «Голосовой блокнот» и «Войснот – голос в текст» . После установки их можно найти на закладке «Приложения» вашего браузера «Хром» . (image. 10)

    Расширения называются «Google Voice Search Hotword (Beta) 0.1.0.5» и «Голосовой ввод текста — Speechpad.ru 5.4» . После установки их можно будет выключить или удалить на вкладке «Расширения» . (image. 11)

    VoiceNote . На вкладке приложения в браузере «Хром» дважды щелкните иконку программы. Откроется диалоговое окно как на картинке ниже. Нажав на значке микрофона, вы говорите в микрофон короткие фразы. Программа передает ваши слова на сервер по распознанию речи и набирает текст в окне. Все слова и фразы, показанные на иллюстрации, были набраны с первого раза. Очевидно, что этот способ работает только при активном подключении к Интернету. (image. 12)

    Голосовой блокнот . Если запустить программу на вкладке приложений, то откроется новая вкладка Интернет страницы Speechpad.ru . Там есть подробная инструкция, как пользоваться этой службой и компактная форма. Последняя показана на иллюстрации ниже. (image. 13)

    Голосовой ввод текста позволяет заполнять текстовые поля Интернет страниц голосом. Для примера я вышел на свою страницу «Google+» . В поле ввода нового сообщения щелкнул правой кнопкой мыши и выбрал пункт «SpeechPad» . Окрашенное в розовый цвет окно ввода говорит, что можно диктовать ваш текст. (image. 14)

    Google Voice Search позволяет производить поиск голосом. При установке и активации этого расширения в строке поиска появляется символ микрофона. Когда вы его нажмете, появится символ в большом красном круге. Просто скажите поисковую фразу и она появится в результатах поиска. (image. 15)

    Важное замечание: для работы микрофона с расширениями «Хром» вам нужно разрешить доступ к микрофону в настройках браузера. По умолчанию в целях безопасности он запрещен. Пройдите в Настройки→Личные данные→Настройки контента . (Для доступа ко всем настройкам в конце списка щелкните Показать дополнительные настройки) . Откроется диалоговое окно Настройки содержания страницы . Выберите вниз по списку пункт Мультимедиа→микрофон .

    6. Итоги работы с программами распознания русской речи

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

    Теперь можно говорить, что результат разработок Google будет новым критерием для оценки продуктов других производителей. Хотелось бы, чтобы система распознания работала в автономном режиме без обращения к серверам компании –так удобнее и быстрее. Но когда будет выпущена самостоятельная программа по работе с непрерывным потоком русской речи неизвестно. Стоит, однако, предположить, что при возможности тренировки это «творение» станет настоящим прорывом.

    Программы российских разработчиков «Горыныч» , «Диктограф» и «Комбат» я подробно рассмотрю во второй части данного обзора. Эта статья писалась очень медленно по той причине, что сам поиск оригинальных дисков сейчас затруднен. На данный момент у меня уже есть все версии российских «распознавалок» голоса в текст кроме «Комбат 2.52». Ни у кого из моих знакомых или коллег нет этой программы, а я сам имею только несколько хвалебных отзывов на форумах. Правда нашелся такой странный вариант – скачать «Комбат» через SMS, но мне он не нравится. (image16)


    Короткий видео ролик покажет вам, как идет распознание речи в смартфоне с ОС Андроид. Особенность голосового набора — это необходимость подключения к серверам Гугла. Таким образом у вас должен работать Интернет

    В данном телефоне присутствует распознавание речи или голосовой ввод, но работает он только через интернет, подключаясь к сервисам Google. Но телефон можно научить распознавать речь и без интернета, мы рассмотрим как включить распознавание русского языка в оффлайн . Для работы данного метода у вас должны быть установлены два приложения Voice Search и Google Search , хотя в заводской прошивки данные программки уже присутствуют.

    Для прошивки

    Переходим в настройки телефона и выбираем

    Выбираем русский язык и скачиваем его.

    Для прошивки 2.8B

    В новой прошивке пункт меню "Распознавание речи оффлайн " отсутствует.

    Если до обновления прошивки у вас были установлены оффлайн пакеты, и вы не делали вайпов (сброса настроек) при обновлении, то они должны были сохранится. Иначе придется откатываться на прошивку 2.2 , устанавливать голосовые пакеты, а уже потом обновлять систему до 2.8B .

    Для устройств Rev.B

    Устанавливаем апдейт через рекавери и наслаждаемся распознаванием голоса в оййлайн.

    2. Скачиваем базу для русской речи, и копируем на SD-карту

    Скачать Russian_offline.zip 1301

    3. Войти в рекавери, зажав (Громкость + и Вкл ) при выключенном телефоне.

    4. Выбрать Apply update from external storage и выбираем скачанный архив.

    Продукты и технологии:

    Visual Studio, C#, .NET Speech Libraries

    В статье рассматриваются:

    • добавление поддержки распознавания речи к консольному приложению;
    • обработка распознаваемой речи;
    • установка библиотек для распознавания речи;
    • сравнение Microsoft.Speech и System.Speech;
    • добавление поддержки распознавания речи к приложению Windows Forms.

    С появлением Windows Phone Cortana, персонального помощника, активируемого речью (равно как и аналога от фруктовой компании, о котором нельзя упоминать всуе), приложения с поддержкой речи стали занимать все более значимое место в разработке ПО. В этой статье я покажу, как начать работу с распознаванием и синтезом речи в консольных Windows-приложениях, приложениях Windows Forms и Windows Presentation Foundation (WPF).

    Заметьте, что также можете добавить речевые возможности в приложения Windows Phone, веб-приложения ASP.NET, приложения Windows Store, Windows RT и Xbox Kinect, но соответствующие методики отличаются от рассматриваемых в этой статье.

    Хороший способ понять, что именно будет обсуждаться в этой статье, - взглянуть на экранные снимки двух разных демонстрационных программ на рис. 1 и 2 . После запуска консольное приложение на рис. 1 немедленно произносит фразу «I am awake». Конечно, вы не сможете услышать демонстрационное приложение, читая эту статью, поэтому оно отображает текст того, что говорит компьютер. Потом пользователь произносит команду «Speech on». Демонстрационное приложение откликается распознанным текстом, а затем на внутреннем уровне включает прослушивание и реагирует на запросы сложить два числа.

    Рис. 1. Распознавание и синтез речи в консольном приложении


    Рис. 2. Распознавание речи в приложении Windows Forms

    Пользователь попросил приложение сложит один и два, затем два и три. Приложение распознало произнесенные команды и дало ответы голосовым способом. Позднее я опишу более полезные способы применения распознавания речи.

    Далее пользователь сказал «Speech off» - голосовую команду, которая деактивирует прослушивание команд для сложения чисел, но не отключает полностью распознавание речи. После этой речевой команды следующая команда на сложение единицы с двойкой была проигнорирована. Наконец, пользователь снова включил прослушивание команд и произнес бессмысленную команду «Klatu barada nikto», которую приложение распознало как команду на полную деактивацию распознавания речи и свое завершение.

    На рис. 2 показано приложение Windows Forms с включенным холостым распознаванием речи (dummy speech-enabled). Это приложение распознает произносимые команды, но не реагирует на них голосовым выводом. При первом запуске приложения флажок Speech On не был установлен, указывая на то, что распознавание речи не активно. Пользователь установил этот флажок, а затем произнес «Hello». Приложение откликнулось выводом распознанного текста в элементе управления ListBox в нижней части окна.

    Затем пользователь произнес: «Set text box 1 to red». Приложение распознало речь и откликнулось: «Set text box 1 red», что почти (но не совсем) точно соответствует тому, что сказал пользователь. Хотя на рис. 2 этого не видно, текст в элементе управления TextBox в верхней части окна стал действительно красным.

    Потом пользователь произнес: «Please set text box 1 to white». Приложение распознало это как «set text box 1 white» и сделало именно это. В заключение пользователь сказал: «Good-bye», и приложение вывело этот текст, но ничего не стало делать с Windows Forms, хотя могло бы, например, сбросить флажок Speech On.

    Использовать объект синтезатора довольно просто.

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

    Добавление поддержки распознавания речи в консольное приложение

    Чтобы создать демонстрацию, показанную на рис. 1 , я запустил Visual Studio и создал новое консольное приложение на C# с названием ConsoleSpeech. Я успешно использовал речевые средства с Visual Studio 2010 и 2012, но должна подойти любая сравнительно недавняя версия. После загрузки кода шаблона в редактор я переименовал файл Program.cs в окне Solution Explorer в более описательный ConsoleSpeechProgram.cs, и Visual Studio переименовала класс Program за меня.

    Далее я добавил ссылку на файл Microsoft.Speech.dll, который находится в C:\ProgramFiles (x86)\Microsoft SDKs\Speech\v11.0\Assembly. Эта DLL отсутствовала на моем компьютере, и мне пришлось скачивать ее. Установка файлов, необходимых для добавления распознавания и синтеза речи в приложение, не столь уж и тривиальна. Я подробно объясню процесс установки в следующем разделе, а пока допустим, что Microsoft.Speech.dll есть в вашей системе.

    Добавив ссылку на речевую DLL, я удалил из верхней части кода все выражения using, кроме указывавшего на пространство имен System верхнего уровня. Потом я добавил выражения using для пространств имен Microsoft.Speech.Recognition, Microsoft.Speech.Synthesis и System.Globalization. Первые два пространства имен сопоставлены с речевой DLL. Заметьте: существуют и такие пространства имен, как System.Speech.Recognition и System.Speech.Synthesis, что может сбить с толку. Вскоре я поясню разницу между ними. Пространство имен Globalization было доступно по умолчанию и не требовало добавления новой ссылки в проект.

    Весь исходный код демонстрационного консольного приложения приведен на рис. 3 , а также доступен в пакете исходного кода, сопутствующем этой статье. Я убрал всю стандартную обработку ошибок, чтобы по возможности не затуманивать главные идеи.

    Рис. 3. Исходный код демонстрационного консольного приложения

    using System; using Microsoft.Speech.Recognition; using Microsoft.Speech.Synthesis; using System.Globalization; namespace ConsoleSpeech { class ConsoleSpeechProgram { static SpeechSynthesizer ss = new SpeechSynthesizer(); static SpeechRecognitionEngine sre; static bool done = false; static bool speechOn = true; static void Main(string args) { try { ss.SetOutputToDefaultAudioDevice(); Console.WriteLine("\n(Speaking: I am awake)"); ss.Speak("I am awake"); CultureInfo ci = new CultureInfo("en-us"); sre = new SpeechRecognitionEngine(ci); sre.SetInputToDefaultAudioDevice(); sre.SpeechRecognized += sre_SpeechRecognized; Choices ch_StartStopCommands = new Choices(); ch_StartStopCommands.Add("speech on"); ch_StartStopCommands.Add("speech off"); ch_StartStopCommands.Add("klatu barada nikto"); GrammarBuilder gb_StartStop = new GrammarBuilder(); gb_StartStop.Append(ch_StartStopCommands); Grammar g_StartStop = new Grammar(gb_StartStop); Choices ch_Numbers = new Choices(); ch_Numbers.Add("1"); ch_Numbers.Add("2"); ch_Numbers.Add("3"); ch_Numbers.Add("4"); GrammarBuilder gb_WhatIsXplusY = new GrammarBuilder(); gb_WhatIsXplusY.Append("What is"); gb_WhatIsXplusY.Append(ch_Numbers); gb_WhatIsXplusY.Append("plus"); gb_WhatIsXplusY.Append(ch_Numbers); Grammar g_WhatIsXplusY = new Grammar(gb_WhatIsXplusY); sre.LoadGrammarAsync(g_StartStop); sre.LoadGrammarAsync(g_WhatIsXplusY); sre.RecognizeAsync(RecognizeMode.Multiple); while (done == false) { ; } Console.WriteLine("\nHit < enter > to close shell\n"); Console.ReadLine(); } catch (Exception ex) { Console.WriteLine(ex.Message); Console.ReadLine(); } } // Main static void sre_SpeechRecognized(object sender, SpeechRecognizedEventArgs e) { string txt = e.Result.Text; float confidence = e.Result.Confidence; Console.WriteLine("\nRecognized: " + txt); if (confidence < 0.60) return; if (txt.IndexOf("speech on") >= 0) { Console.WriteLine("Speech is now ON"); speechOn = true; } if (txt.IndexOf("speech off") >= 0) { Console.WriteLine("Speech is now OFF"); speechOn = false; } if (speechOn == false) return; if (txt.IndexOf("klatu") >= 0 && txt.IndexOf("barada") >= 0) { ((SpeechRecognitionEngine)sender). RecognizeAsyncCancel(); done = true; Console.WriteLine("(Speaking: Farewell)"); ss.Speak("Farewell"); } if (txt.IndexOf("What") >= 0 && txt.IndexOf("plus") >= 0) { string words = txt.Split(" "); int num1 = int.Parse(words); int num2 = int.Parse(words); int sum = num1 + num2; Console.WriteLine("(Speaking: " + words + " plus " + words + " equals " + sum + ")"); ss.SpeakAsync(words + " plus " + words + " equals " + sum); } } // sre_SpeechRecognized } // Program } // ns

    После выражений using демонстрационный код начинается так:

    namespace ConsoleSpeech { class ConsoleSpeechProgram { static SpeechSynthesizer ss = new SpeechSynthesizer(); static SpeechRecognitionEngine sre; static bool done = false; static bool speechOn = true; static void Main(string args) { ...

    Объект SpeechSynthesizer на уровне класса дает возможность приложению синтезировать речь. Объект SpeechRecognitionEngine позволяет приложению прослушивать и распознавать произносимые слова или фразы. Булева переменная done определяет, когда завершается приложение в целом. Булева переменная speechOn управляет тем, слушает ли приложение какие-то команды, кроме команды на выход из программы.

    Здесь идея в том, что консольное приложение не принимает набираемый с клавиатуры ввод, поэтому оно всегда слушает команды. Однако, если speechOn равна false, распознается и выполняется только команда на выход из программы; прочие команды распознаются, но игнорируются.

    Метод Main начинается так:

    try { ss.SetOutputToDefaultAudioDevice(); Console.WriteLine("\n(Speaking: I am awake)"); ss.Speak("I am awake");

    Экземпляр объекта SpeechSynthesizer был создан при его объявлении. Использовать объект синтезатора довольно просто. Метод SetOutputToDefaultAudioDevice отправляет вывод на динамики, подключенные к вашему компьютеру (вывод можно отправлять и в файл). Метод Speak принимает строку, а затем произносит ее. Вот так все несложно.

    Распознавание речи гораздо сложнее ее синтеза. Метод Main продолжает созданием объекта распознавателя:

    CultureInfo ci = new CultureInfo("en-us"); sre = new SpeechRecognitionEngine(ci); sre.SetInputToDefaultAudioDevice(); sre.SpeechRecognized += sre_SpeechRecognized;

    Сначала в объекте CultureInfo указывается распознаваемый язык, в данном случае United States English. Объект CultureInfo находится в пространстве имен Globalization, на которое мы сослались с помощью выражения using. Затем после вызова конструктора SpeechRecognitionEngine голосовой ввод назначается аудиоустройству по умолчанию - чаще всего микрофону. Заметьте, что в большинстве лэптопов есть встроенный микрофон, но на настольных компьютерах потребуется внешний микрофон (в наши дни он часто комбинируется с наушниками).

    Ключевым методом для объекта распознавателя является обработчик событий SpeechRecognized. При использовании Visual Studio, если вы введете «sre.SpeechRecognized +=» и подождете долю секунды, IntelliSense автоматически закончит ваше выражение именем обработчика событий - sre_SpeechRecognized. Советую нажать клавишу Tab, чтобы согласиться с предложенным вариантом и использовать это имя по умолчанию.

    Choices ch_Numbers = new Choices(); ch_Numbers.Add("1"); ch_Numbers.Add("2"); ch_Numbers.Add("3"); ch_Numbers.Add("4"); // с технической точки зрения, // это Add(new string { "4" }); GrammarBuilder gb_WhatIsXplusY = new GrammarBuilder(); gb_WhatIsXplusY.Append("What is"); gb_WhatIsXplusY.Append(ch_Numbers); gb_WhatIsXplusY.Append("plus"); gb_WhatIsXplusY.Append(ch_Numbers); Grammar g_WhatIsXplusY = new Grammar(gb_WhatIsXplusY);

    Три основных объекта здесь - это набор Choices, шаблон GrammarBuilder и управляющий Grammar. Когда я создаю Grammar для распознавания, я начинаю с перечисления некоторых конкретных примеров того, что мне нужно распознавать. Скажем, «What is one plus two?» и «What is three plus four?».

    Потом я определяю соответствующий универсальный шаблон, например «What is plus ?». Шаблоном является GrammarBuilder, а конкретные значения, которые передаются шаблону, - это набор Choices. Объект Grammar инкапсулирует шаблон и Choices.

    В демонстрационной программе я ограничиваю для сложения от 1 до 4 и добавляю их как строки в набор Choices. Более эффективный подход:

    string numbers = new string { "1", "2", "3", "4" }; Choices ch_Numbers = new Choices(numbers);

    Я представляю вам менее эффективный подход к созданию набора Choices по двум причинам. Во-первых, добавление одной строки единовременно было единственным подходом, который я видел в других примерах с распознаванием речи. Во-вторых, вы могли подумать, что добавление одной строки единовременно вообще не должно работать; Visual Studio IntelliSense в реальном времени показывает, что одна из перегрузок Add принимает параметр типа params string phrases. Если вы не заметили ключевое слово params, то, возможно, сочли, что метод Add принимает только массивы строк, а одну строку - нет. Но это не так: он принимает и то, и другое. Я советую передавать массив.

    Создание набора Choices из последовательных чисел в какой-то мере является особым случаем и дает возможность использовать программный подход наподобие:

    string numbers = new string; for (int i = 0; i < 100; ++i) numbers[i] = i.ToString(); Choices ch_Numbers = new Choices(numbers);

    После создания Choices для заполнения слотов GrammarBuilder демонстрационная программа создает GrammarBuilder, а затем управляющий Grammar:

    GrammarBuilder gb_WhatIsXplusY = new GrammarBuilder(); gb_WhatIsXplusY.Append("What is"); gb_WhatIsXplusY.Append(ch_Numbers); gb_WhatIsXplusY.Append("plus"); gb_WhatIsXplusY.Append(ch_Numbers); Grammar g_WhatIsXplusY = new Grammar(gb_WhatIsXplusY);

    Похожий шаблон демонстрационная программа использует при создании Grammar для команд, относящихся к старту и остановке:

    Choices ch_StartStopCommands = new Choices(); ch_StartStopCommands.Add("speech on"); ch_StartStopCommands.Add("speech off"); ch_StartStopCommands.Add("klatu barada nikto"); GrammarBuilder gb_StartStop = new GrammarBuilder(); gb_StartStop.Append(ch_StartStopCommands); Grammar g_StartStop = new Grammar(gb_StartStop);

    Грамматики можно определять очень гибко. Здесь команды «speech on», «speech off» и «klatu barada nikto» помещаются в одну грамматику, так как они логически связаны. Эти три команды можно было бы определить в трех разных грамматиках или поместить команды «speech on» и «speech off» в одну грамматику, а команду «klatu barada nikto» - во вторую.

    Создав все объекты Grammar, вы помещаете их в распознаватель речи, и распознавание речи активируется:

    sre.LoadGrammarAsync(g_StartStop); sre.LoadGrammarAsync(g_WhatIsXplusY); sre.RecognizeAsync(RecognizeMode.Multiple);

    Аргумент RecognizeMode.Multiple необходим, когда у вас более одной грамматики, что будет во всех программах, кроме самых простейших. Метод Main завершается следующим образом:

    While (done == false) { ; } Console.WriteLine("\nHit < enter > to close shell\n"); Console.ReadLine(); } catch (Exception ex) { Console.WriteLine(ex.Message); Console.ReadLine(); } } // Main

    Странно выглядящий пустой цикл while позволяет сохранить работающей оболочку консольного приложения. Цикл будет завершен, когда булева переменная done уровня класса будет установлена в true обработчиком событий распознавания речи.

    Обработка распознаваемой речи

    Код обработки событий, связанных с распознаванием речи, начинается так:

    static void sre_SpeechRecognized(object sender, SpeechRecognizedEventArgs e) { string txt = e.Result.Text; float confidence = e.Result.Confidence; Console.WriteLine("\nRecognized: " + txt); if (confidence < 0.60) return; ...

    Распознанный текст хранится в свойстве Result.Text объекта SpeechRecognizedEventArgs. Кроме того, можно использовать набор Result.Words. Свойство Result.Confidence хранит значение от 0.0 до 1.0, которое является примерной оценкой того, насколько произнесенный текст соответствует любой из грамматик, связанных с распознавателем. Демонстрационная программа инструктирует обработчик событий игнорировать текст с низкой достоверностью (low confidence) распознанного текста.

    Значения Confidence сильно зависят от сложности ваших грамматик, качества микрофона и других факторов. Например, если демонстрационной программе нужно распознавать лишь числа от 1 до 4, то значения достоверности на моем компьютере обычно находятся на уровне 0.75. Но, если грамматика должна распознавать числа от 1 до 100, значения достоверности падают приблизительно до 0.25. Если в двух словах, то обычно вы должны экспериментировать со значениями достоверности, чтобы добиться хороших результатов распознавания речи.

    if (txt.IndexOf("speech on") >= 0) { Console.WriteLine("Speech is now ON"); speechOn = true; } if (txt.IndexOf("speech off") >= 0) { Console.WriteLine("Speech is now OFF"); speechOn = false; } if (speechOn == false) return;

    Хотя, возможно, это не совсем очевидно поначалу, эта логика должна иметь смысл, если вдуматься в нее. Затем обрабатывается секретная команда выхода:

    if (txt.IndexOf("klatu") >= 0 && txt.IndexOf("barada") >= 0) { ((SpeechRecognitionEngine)sender).RecognizeAsyncCancel(); done = true; Console.WriteLine("(Speaking: Farewell)"); ss.Speak("Farewell"); }

    Заметьте, что механизм распознавания речи может на самом деле распознавать бессмысленные слова. Если объект Grammar содержит слова, отсутствующие во встроенном словаре этого объекта, Grammar пытается по возможности идентифицировать такие слова, используя семантическую эвристику, и обычно весьма успешно. Вот почему я использовал «klatu» вместо правильного «klaatu» (из одного старого научно-фантастического фильма).

    Также заметьте, что вы не обязаны обрабатывать весь распознанный Grammar текст («klatu barada nikto») - нужно лишь иметь достаточно информации для уникальной идентификации грамматической фразы («klatu» и «barada»).

    If (txt.IndexOf("What") >= 0 && txt.IndexOf("plus") >= 0) { string words = txt.Split(" "); int num1 = int.Parse(words); int num2 = int.Parse(words); int sum = num1 + num2; Console.WriteLine("(Speaking: " + words + " plus " + words + " equals " + sum + ")"); ss.SpeakAsync(words + " plus " + words + " equals " + sum); } } // sre_SpeechRecognized } // Program } // ns

    Обратите внимание на то, что текст в Results.Text чувствителен к регистру букв («What» и «what»). Распознав фразу, ее можно разобрать на конкретные слова. В данном случае распознанный текст имеет форму «What is x plus y», поэтому «What» помещается в words, а два складываемых числа (как строки) сохраняются в words и words.

    Установка библиотек

    Объяснение демонстрационной программы подразумевает, что все необходимые речевые библиотеки установлены на вашем компьютере. Чтобы создавать и запускать демонстрационные программы, нужно установить четыре пакета: SDK (обеспечивает возможность создания демонстраций в Visual Studio), исполняющую среду (выполняет демонстрации после их создания), распознаваемый и синтезируемый (произносимый программой) языки.

    Чтобы установить SDK, поищите в Интернете по словосочетанию «Speech Platform 11 SDK». Это приведет вас на нужную страницу в Microsoft Download Center (рис. 4 ). Щелкнув кнопку Download, вы увидите варианты, показанные на рис. 5 . SDK поставляется в 32- и 64-разрядной версиях. Я настоятельно советую использовать 32-разрядную версию независимо от разрядности вашей системы. 64-разрядная версия не взаимодействует с некоторыми приложениями.


    Рис. 4. Основная страница установки SDK в Microsoft Download Center


    Рис. 5. Установка Speech SDK

    Вам не нужно ничего, кроме одного файла.msi под x86 (для 32-разрядных систем). Выбрав этот файл и щелкнув кнопку Next, вы можете запустить программу установки прямо отсюда. Речевые библиотеки не дают особой обратной связи насчет того, когда установка закончена, поэтому не ищите никаких сообщений об успешном завершении.


    Рис. 6. Установка исполняющей среды

    Крайне важно выбрать ту же версию платформы (в демонстрации - 11) и разрядность (32 или 64 ), что и у SDK. И вновь я настоятельно советую 32-разрядную версию, даже если вы работаете в 64-разрядной системе.

    Затем можно установить распознаваемый язык (recognition language). Страница скачивания приведена на рис. 7 . В демонстрационной программе используется файл MSSpeech_SR_en-us_TELE.msi (English-U.S.). SR расшифровывается как распознавание речи (speech recognition), а TELE - как телефония; это означает, что распознаваемый язык предназначен для работы с низкокачественным аудиовходом, например от телефона или настольного микрофона.


    Рис. 7. Установка распознаваемого языка

    Наконец, вы можете установить язык и голос для синтеза речи. Страница скачивания приведена на рис. 8 . Демонстрационная программа использует файл MSSpeech_TTS_en-us_Helen.msi. TTS (text-to-speech), по сути, является синонимом синтеза речи (speech synthesis). Обратите внимание на два доступных голоса English, U.S. Есть и другие голоса English, но не U.S. Создание файлов языка синтеза - задача весьма сложная. Однако можно приобрести и установить другие голоса от множества компаний.


    Рис. 8. Установка голоса и языка синтеза

    Любопытно, что, хотя язык распознавания речи и голос/язык синтеза речи на самом деле являются совершенно разными вещами, оба пакета являются вариантами на одной странице скачивания. Download Center UI позволяет отметить как язык распознавания, так и язык синтеза, но попытка одновременной их установки оказалась для меня катастрофичной, поэтому я рекомендую устанавливать их по отдельности.

    Сравнение Microsoft.Speech с System.Speech

    Если вы новичок в распознавании и синтезе речи для Windows-приложений, вы можете легко запутаться в документации, потому что существует несколько речевых платформ. В частности, помимо библиотеки Microsoft.Speech.dll, используемой демонстрационными программами в этой статье, есть библиотека System.Speech.dll, являющаяся частью операционной системы Windows. Эти две библиотеки похожи в том смысле, что их API почти, но не полностью идентичны. Поэтому, если вы отыскиваете примеры обработки речи в Интернете и видите фрагменты кода, а не полные программы, то совершенно не очевидно, относится данный пример к System.Speech или Microsoft.Speech.

    Если вы новичок в обработке речи, используйте для добавления поддержки речи в.NET-приложение библиотеку Microsoft.Speech, а не System.Speech.

    Хотя обе библиотеки имеют общую основную кодовую базу и похожие API, они определенно разные. Неокторые ключевые различия суммированы в табл. 1 .

    Табл. 1. Основные различия между Microsoft.Speech и System.Speech

    System.Speech DLL - часть ОС, поэтому она установлена в каждой системе Windows. Microsoft.Speech DLL (и связанные с ней исполняющая среда и языки) нужно скачивать и устанавливать в систему. Распознавание с применением System.Speech обычно требует обучения под конкретного пользователя, когда пользователь начитывает какой-то текст, а система учится понимать произношение, свойственное этому пользователю. Распознавание с применением Microsoft.Speech работает сразу для любого пользователя. System.Speech может распознавать практически любые слова (это называет свободной диктовкой). Microsoft.Speech будет распознавать лишь те слова и фразы, которые имеются в объекте Grammar, определенном в программе.

    Добавление поддержки распознавания речи к приложению Windows Forms

    Процесс добавления поддержки распознавания и синтеза речи к приложению Windows Forms или WPF похож на таковой для консольного приложения. Чтобы создать демонстрационную программу, показанную на рис. 2 , я запустил Visual Studio, создал новое приложение C# Windows Forms и переименовал его в WinFormSpeech.

    После загрузки кода шаблона в редактор я добавил ссылку на файл Microsoft.Speech.dll в окне Solution Explorer - так же, как я сделал это в консольной программе. В верхней части исходного кода я удалил ненужные выражения using, оставив только ссылки на пространства имен System, Data, Drawing и Forms. Затем добавил два выражения using для пространств имен Microsoft.Speech.Recognition и System.Globalization.

    Демонстрация на основе Windows Forms не использует синтез речи, поэтому я не ссылаюсь на библиотеку Microsoft.Speech.Synthesis. Добавление синтеза речи в приложение Windows Forms осуществляется точно так же, как и в консольном приложении.

    В Visual Studio в режиме проектирования я перетащил на Form элементы управления TextBox, CheckBox и ListBox. Дважды щелкнул CheckBox, и Visual Studio автоматически создал скелет метода-обработчика событий CheckChanged.

    Вспомните, что демонстрационная консольная программа сразу же начинала прослушивать произносимые команды и продолжала делать это вплоть до своего завершения. Этот подход можно применить и в приложении Windows Forms, но вместо него я решил дать возможность пользователю включать и выключать распознавание речи с помощью элемента управления CheckBox (т. е. с помощью флажка).

    Исходный код в файле Form1.cs демонстрационной программы, где определен частичный класс, представлен на рис. 9 . Объект механизма распознавания речи объявляется и создается как член Form. В конструкторе Form я подключаю обработчик событий SpeechRecognized, а затем создаю и загружаю два объекта Grammars:

    public Form1() { InitializeComponent(); sre.SetInputToDefaultAudioDevice(); sre.SpeechRecognized += sre_SpeechRecognized; Grammar g_HelloGoodbye = GetHelloGoodbyeGrammar(); Grammar g_SetTextBox = GetTextBox1TextGrammar(); sre.LoadGrammarAsync(g_HelloGoodbye); sre.LoadGrammarAsync(g_SetTextBox); // sre.RecognizeAsync() находится // в обработчике события CheckBox }

    Рис. 9. Добавление поддержки распознавания речи в Windows Forms

    using System; using System.Data; using System.Drawing; using System.Windows.Forms; using Microsoft.Speech.Recognition; using System.Globalization; namespace WinFormSpeech { public partial class Form1: Form { static CultureInfo ci = new CultureInfo("en-us"); static SpeechRecognitionEngine sre = new SpeechRecognitionEngine(ci); public Form1() { InitializeComponent(); sre.SetInputToDefaultAudioDevice(); sre.SpeechRecognized += sre_SpeechRecognized; Grammar g_HelloGoodbye = GetHelloGoodbyeGrammar(); Grammar g_SetTextBox = GetTextBox1TextGrammar(); sre.LoadGrammarAsync(g_HelloGoodbye); sre.LoadGrammarAsync(g_SetTextBox); // sre.RecognizeAsync() находится // в обработчике события CheckBox } static Grammar GetHelloGoodbyeGrammar() { Choices ch_HelloGoodbye = new Choices(); ch_HelloGoodbye.Add("hello"); ch_HelloGoodbye.Add("goodbye"); GrammarBuilder gb_result = new GrammarBuilder(ch_HelloGoodbye); Grammar g_result = new Grammar(gb_result); return g_result; } static Grammar GetTextBox1TextGrammar() { Choices ch_Colors = new Choices(); ch_Colors.Add(new string { "red", "white", "blue" }); GrammarBuilder gb_result = new GrammarBuilder(); gb_result.Append("set text box 1"); gb_result.Append(ch_Colors); Grammar g_result = new Grammar(gb_result); return g_result; } private void checkBox1_CheckedChanged(object sender, EventArgs e) { if (checkBox1.Checked == true) sre.RecognizeAsync(RecognizeMode.Multiple); else if (checkBox1.Checked == false) // выключено sre.RecognizeAsyncCancel(); } void sre_SpeechRecognized(object sender, SpeechRecognizedEventArgs e) { string txt = e.Result.Text; float conf = e.Result.Confidence; if (conf < 0.65) return; this.Invoke(new MethodInvoker(() => { listBox1.Items.Add("I heard you say: " + txt); })); // специфика WinForm if (txt.IndexOf("text") >= 0 && txt.IndexOf("box") >= 0 && txt.IndexOf("1")>= 0) { string words = txt.Split(" "); this.Invoke(new MethodInvoker(() => { textBox1.Text = words; })); // специфика WinForm } } } // Form } // ns

    Я мог бы создать два объекта Grammar напрямую, как в консольной программе, но вместо этого, что сделать код чуточку понятнее, определил два вспомогательных метода (GetHelloGoodbyeGrammar и GetTextBox1TextGrammar), которые и выполняют эту работу.

    static Grammar GetTextBox1TextGrammar() { Choices ch_Colors = new Choices(); ch_Colors.Add(new string { "red", "white", "blue" }); GrammarBuilder gb_result = new GrammarBuilder(); gb_result.Append("set text box 1"); gb_result.Append(ch_Colors); Grammar g_result = new Grammar(gb_result); return g_result; }

    Этот вспомогательный метод будет распознавать фразу «set text box 1 red». Однако пользователь не обязан точно проговаривать эту фразу. Например, он мог бы произнести: «Please set the text in text box 1 to red», и механизм распознавания речи все равно опознал бы фразу как «set text box 1 red» - пусть и с более низким значением достоверности, чем при точном совпадении с шаблоном Grammar. Другими словами, создавая объекты Grammar, вы не обязаны принимать во внимание все вариации фразы. Это радикально упрощает использование распознавания речи.

    Обработчик событий для CheckBox определен так:

    private void checkBox1_CheckedChanged(object sender, EventArgs e) { if (checkBox1.Checked == true) sre.RecognizeAsync(RecognizeMode.Multiple); else if (checkBox1.Checked == false) // выключено sre.RecognizeAsyncCancel(); }

    Объект механизма распознавания речи, sre (speech recognition engine), всегда существует в течение всего срока жизни приложения Windows Forms. Этот объект активируется и деактивируется вызовами методов RecognizeAsync и RecognizeAsyncCancel, когда пользователь соответственно переключает CheckBox.

    Определение обработчика событий SpeechRecognized начинается с:

    void sre_SpeechRecognized(object sender, SpeechRecognizedEventArgs e) { string txt = e.Result.Text; float conf = e.Result.Confidence; if (conf < 0.65) return; ...

    Помимо более-менее постоянно используемых свойств Result.Text и Result.Confidence, объект Result имеет несколько других полезных, но более сложных свойств, которые вы, возможно, захотите исследовать; например, Homophones и ReplacementWordUnits. Кроме того, механизм распознавания речи предоставляет несколько полезных событий вроде SpeechHypothesized.

    this.Invoke((Action)(() => listBox1.Items.Add("I heard you say: " + txt)));

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

    Заключение

    Информация, представленная в этой статье, должна дать вам возможность сразу же приступить к работе, если вы хотите исследовать синтез и распознавание речи в.NET-приложениях. Освоение самой технологии не составляет особого труда, как только вы минуете ухабы начального обучения и установки компонентов. Настоящая проблема в синтезе и распознавании речи - понимание того, когда это действительно полезно.

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

    Другое возможное применение речи в консольной программе - распознавание команд вроде «Launch Notepad» и «Launch Word». Иначе говоря, такая консольная программа может использоваться на вашем компьютере для выполнения действий, которые в ином случае потребовали бы множества манипуляций с клавиатурой и мышью.

    Джеймс Маккафри (Dr. James McCaffrey) работает на Microsoft Research в Редмонде (штат Вашингтон). Принимал участие в создании нескольких продуктов Microsoft, в том числе Internet Explorer и Bing. С ним можно связаться по адресу [email protected] .

    Выражаю благодарность за рецензирование статьи экспертам Microsoft Research Робу Грюну (Rob Gruen), Марку Маррону (Mark Marron) и Кертису фон Ве (Curtis von Veh).