ФОРУМ КУПИТЬ

Последние статьи

ВСЕ СТАТЬИ

Управление голосом. Распознавание русской речи

27/04/2011 18:05:07

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

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

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

Не буду глубоко вникать в современную теорию распознавания речи. Скажу только, что пробовал программный пакет CMU sphinx 0.6.1 с русской акустической моделью. Результаты распознавания были неудовлетворительными. Даже англоязычная модель "угадывала" фразу только в 50% случаев. Управлять автоматизированной системой с помощью такой программы не представлялось возможным. Но вот в сети появились первые упоминания о Google Speech API. Я не преминул воспользоваться этим он-лайн сервисом и был просто ошеломлен качеством распознавания.

Сервис Google Speech создавался корпорацией Google для голосового поиска. Нужно что-нибудь найти в Интернете, говорим фразу, а Google ищет. Удобно для всякого рода мобильных гаджетов. Но поиск нас не интересует. Нас интересует технология. К счастью, почти для каждого своего сервиса Google предоставляет API, которое позволяет использовать сервис в своих приложениях. А это как раз то, что нам нужно. В современном мире и в современном доме наличие электроэнергии почти всегда связано с наличием Интернета, поэтому я не переживаю, что таким образом создается некоторая зависимости определенной функции системы от наличия сети и работы сервиса. Тем более, что эта функция скорее относится к разряду приятных опций.

Но вернемся к нашим пингвинам. В Linux для реализации полноценного управления голосом все есть. Первое, что необходимо, это подключить микрофон к серверу и заставить его слушать эфир на предмет громких звуков или команд. Для этого нам понадобиться сверхпопулярнейшая программа sox, которую разработчики называют так "Swiss Army knife of audio manipulation". Красивая метафора.

apt-get install sox
apt-get install flac

Теперь пишем простой как пареная репа shell-скрипт.

#!/bin/bash

while [ true ]; do
     rec -q -c 1 -r 16000 current.wav silence 1 0.3 3% 1 0.3 3%
     flac -f -s current.wav -o current.flac
     php texttocmd.php
done

Программа sox слушает микрофон и когда обнаруживает наличие звука, записывает фрагмент в wav файл.
Далее этот wav файл конвертируется в формат FLAC.
После этого запускается PHP-скрипт, в котором реализовано обращение к Google Speech API и анализ ответа на предмет полезных команд.

Важно. Записывать звук нужно с частотой 16КГц. Больше не нравится Google, меньше страдает качество. Google не принимает WAV, зато принимает FLAC (это такой формат, который позволяет сжимать аудио без потерь).

Что может быть проще паренной репы и описанного выше shell-скрипта? Да только следующий PHP-скрипт.

<?
// Используем cURL для формирования HTTP POST-запроса к Google API
// Пакет php5-curl в Debian
$file_to_upload = array('myfile'=>'@current.flac');
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,"https://www.google.com/speech-api/v1/recognize?xjerr=1&client=chromium&lang=ru-RU");
curl_setopt($ch, CURLOPT_POST,1);
curl_setopt($ch, CURLOPT_HTTPHEADER, array("Content-Type: audio/x-flac; rate=16000"));
curl_setopt($ch, CURLOPT_POSTFIELDS, $file_to_upload);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
$result=curl_exec ($ch);
curl_close ($ch);

// Описываем команды, которые мы будем выполнять
$cmd_matrix = array(
        array(array("включ", "свет"), "switch on"),
        array(array("выключ", "свет"), "switch off")
        );

// Google возвращает JSON, поэтому парсим стандартной функцией. Доступна в PHP 5.2
$json_array = json_decode($result, true);
$voice_cmd = $json_array["hypotheses"][0]["utterance"];

// Ищем в ответе Google наши команды.
// Если находим, выполняем заранее запрограммированное действие. В данном случае, вывод на экран
for ( $i = 0; $i < count($cmd_matrix); $i++ )
{
        $ok = 1;
        for ( $k = 0; $k < count($cmd_matrix[$i][0]); $k++ )
        {
                if ( !preg_match("/".$cmd_matrix[$i][0][$k]."/", $voice_cmd) )
                $ok = 0;
        }
        if ( $ok == 1 )
        echo $cmd_matrix[$i][1];
}

?>

Запускаем shell-скрипт. Небрежно бросаем фразу типа "Включить свет". Видим на экране что-то вроде того:

{"status":0,"id":"84e08bf5efc17fa7856333560d6faba8-1","hypotheses":[{"utterance":"включить
свет","confidence":0.56143415}]}
включить свет
switch on

Мы отправили POST запрос в Google Speech API. Получили и распарсили ответ, определили - есть ли в ответе ключевые слова, которые задают команду и выполнили ее. Все.
Скорость работы этой цепочки с Интернетом 4Мбит/1Мбит даже быстрее, чем реализация той же задачи на локальном компьютере средствами CMU sphinx. Наверное, аппаратные возможности электронно-вычислительного центра Google превосходят мои.

В массиве cmd_matrix описывается набор слов, которые соответствуют определенной команде. Массив можно заполнять из БД. Ради наглядности я не стал усложнять скрипт. Логика скрипта такова, что можно сказать: "Включить свет", а можно, "Эй, там, включите свет!", а можно "Свет включите, пожалуйста". Во всех случаях свет включится. Каждая ячейка массива cmd_matrix может определять часть слова, слово или фразу. Например, можно задать в массиве не "включ", "свет", а просто "включить свет", тогда алгоритм будет реагировать только на команду "включить свет" и не будет реагировать на команду "свет включить".

Теперь немного из практики. Я думаю, что необходимо придумать Умному Дому имя, а точнее обращение. Любое. Ну там "Любочка" или как в магазине "девушка" или "Бездельник" или "Система". У меня дети зовут робота "Дядей Ваней", потому что он у меня говорит мужским голосом. Зачем нужно имя. А чтобы не было случайных срабатываний. Мы говорим: "Дядя Ваня, включи свет пожалуйста". Он понимает, что обращаются к нему. Своего рода адресация, протокол. ;) После выполнения команды сервер может отчитаться также, с помощью голоса.

Еще немного из практики. Качество распознавания речи очень хорошее, но, конечно, не идеальное. На качество распознавания влияет чувствительность и характеристики микрофона, наличие посторонних фоновых шумов. Так, например, если гаркнуть в микрофон "ВКЛЮЧИТЬ СВЕТ!", Google Speech API может выдать, "ключница". Я сразу вспоминаю, как Иван Васильевич менял профессию "Водку ключница делала?". Главное тут перекрестить сервер, ибо крест животворящий посильнее бубна будет и послушать, что же такое во FLAC-файл записалось. А записалась фраза с перегрузками и хрипом микрофона. Человек то разберет. Он и не то разбирает, а машине за хрипами фразы не слышно. Если в файле содержится чистая внятная речь Google почти в 100% дает правильный результат. У меня однако сложилось впечатление, что мужскую речь при прочих равных система распознает лучше, чем женскую.

При использовании технологии следует обратить внимание на параметр "confidence". Насколько я понимаю, это оценка достоверности. Имеет смысл обрабатывать только те результаты, где значение этого параметра больше 0.5.

Google, насколько я понимаю, официально не представлял Google Speech API. Пока неясно будет ли сохранен к API доступ в будущем и на какой основе. Учитывая всю предыдущую политику компании, думаю, доступ останется, а проект получит развитие.

Да, если у вас компьютер оснащен Intel HDA Audio и вы счастливый пользователь Debian, то знайте, что я сэкономил вам волосы на голове. Вы можете обнаружить, что микрофон у вас не работает и что его вообще нет в микшере. Не крутите ползунки и не дергайте мышь, скачайте с официального сайта последнюю версию ALSA (например, 1.0.24) и установите с помощью джентельменского набора ./configure;make;make install и будет вам счастье. С родной для lenny версией 1.0.17 ничего не выйдет.

 

Автор: Andrey_B
Любое использование материалов сайта возможно только с разрешения автора и с обязательным указанием источника.



Добавить комментарий:

(необязательно, не отображается на сайте)


Сортировка комментариев: Последние сверху | Первые сверху

2013-05-07 09:44:32 | Александр
А как этот скрипт, на горячую клавишу замутить? Меня не устраивает тот вариант, что комп постоянно в ожидании. Кнопку нажал, сказал, выполнилось!


2013-05-06 23:31:09 | Andrey_B
Сергей, на форуме все-таки давалось решение этой проблемы. Дело в том, что Google изменил процедуру доступа к API. Теперь нужен сертификат. Но проблема решается и она была описана. Ваша ошибка скорее всего говорит о том, что Google не вернул никакого ответа.


2013-05-04 21:29:29 | Сергей
Можно ли что-то сделать с PHP Notice: Undefined offset: 0 in /home/stas/Workplace/php/texttocmd.php on line 22
Форум посмотрел, но ответа так и не нашёл.


2012-05-25 09:28:05 | dima
к вопросу о большом брате. А если первичный разбор команд делать у себя, а последующие команды так скажем все что после "Дядя Ваня" уже отправлять на гугл?


2012-04-22 00:31:50 | Серега
Попробовал Ваш метод. Очень плохо распознает... Я так понимаю нужен хороший микрофон? Потому как у меня на дешевом очень медленно разбивает на части и гугл плохо распознает.


2012-02-18 15:53:02 | Andrey_B
stas, это скорее всего значит, что Google ничего не ответил. Поищите на нашем форуме. Там указано, какие надо внести изменения в код, чтобы он заработал.


2012-02-18 14:44:46 | stas
Тут уже проскакивал этот вопрос, но я ничего не понял.
В консоль постоянно выходит ошибка
PHP Notice: Undefined offset: 0 in /home/stas/Workplace/php/texttocmd.php on line 22
на 22-ой строчке у меня
$voice_cmd = $json_array["hypotheses"][0]["utterance"];
Скажите, пожалуйста, что это значит?


2012-02-06 18:33:32 | Andrey_B
Я уже высказывался неоднократно по поводу морально-этической стороны данного вопроса. Здесь каждый вправе сам решать. К сожалению бесплатные продукты, которые можно установить локально, дают неудовлетворительное качество распознавания русской речи или же их нужно натренировывать на свой голос, а лично мне это не очень интересно.


2012-02-06 18:21:45 | артем
Вас не беспокоит, что корпорация добра теперь постоянно слушает ваши частные переговоры?

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

Возможно ли по средствам CMU sphinx 0.6.1 или нейронных сетей добиться того, чтобы можно было распознать слова "дядя Ваня" среди всей остальной болтовни? Как это лучше сделать?


2012-02-02 06:50:44 | vampireos
а не кто не сталкивался?

строка 6: команда не найдена

тобишь

curl_setopt($ch, CURLOPT_URL,"https:/www.google.com/speech-api/v1/recognize?xjerr=1&client=chromium&lang=ru-RU");

и

HTTP method GET is not supported by this URL
Error 405

гугл апи закрыл что ли?


2011-11-05 22:13:13 | Andrey_B
Дмитрий, это команда означает буквально следующее:
Вырезать тишину до момента определения 0.3 секунд звука, а затем вырезать все после определения 0.3 секунды тишины. То есть это команда из целого куска записи вырезает только кусок со сказанной фразой. 3% - это порог тишины. То есть для идеальной тишины - это 0%, но в аналоговом аудио такого не бывает, поэтому нужно ставить 2-3%.


2011-11-03 23:44:44 | Дмитрий
а что обозначают параметры команды rec :
silence 1 0.3 3% 1 0.3 3%


2011-10-24 18:48:08 | Evgeniy
Господа, в 2007 году я использовал вот эту утилитку : www.kiecza.net/daniel/linux/
Очень маленькая и лёгкая. Работала просто отлично. Правда требует обучения, но процесс не напрягает. С 5-8 образцами каждой команды распознавание было порядка 95% (моё субъективное мнение). Использовалась мной на планшете samsung q1, у которого на "морде" 2 микрофона (типа стерео). Утилитка CVoiceControl (так она обзывается) изначально сделана для привязки к sh-скриптам. Собственно полное название Console Voice Control. Лично я пользовался python-ом с небольшими элементами на bash. Все, кто видел моё "общение" с планшетом были просто в шоке! Единственный недостаток - невозможность управления системой при воспроизведении звука через встроенные динамики. Т.е. дать команду "пауза" при воспроизведении фильма не получалось по понятным причинам:) Есть производная от этой утилитки с названием KVoiceControl. Как можно догадаться из названия, точилась под KDE. Её я не пробовал в виду самодостаточности и универсальности CVoiceControl.
В общем всё было хорошо, тулза работала, успешно переживала обновления, но вот год назад на этом планшете помер HDD. Поставил систему с нуля, а собрать и воспользоваться CVoiceControl уже не получилось. Точно не помню, что были за проблемы, но решить их не удалось. Да особо и не пытался, отдал планшет киндеру:)


2011-09-07 17:04:11 | Andrey_B
Андрей, вы имеете ввиду запуск внешних программ из PHP?
Посмотрите следующие функции: exec(), passthru(), shell_exec(), system()


2011-09-07 14:50:36 | Андрей
И последний вопрос) А как в PHP-скрипте запускать программы?


2011-09-07 13:48:31 | Андрей
sudo apt-get install php5-cli
Для таких неудачников как я))))... В убунте чтоб команда php заработала, надо её установить))))... всё прекрасно работает. Автору большущее спасибо))) буду разбираться дальше как мою идею, про понимающего компа доделать)))


2011-09-07 13:28:49 | Андрей
Попробовал... пишет команда не найдена, хоть включить свет, хоть выключить


2011-09-07 12:45:24 | Andrey_B
Андрей, а как наш компьютер поймет когда надо отправлять, а когда нет?
Предложенный в статье алгоритм предполагает, что передача данных в Google API происходит только когда компьютер определил наличие звука и записал этот фрагмент. Естественно компьютер будет реагировать не только на человеческую речь, но и на другие звуки. Однако я предлагаю не уделять сейчас этой проблеме большого внимания. Со временем (а иногда это уже так) скорость соединения с Интернетом будет сравнима со скоростью в локальной сети, а мощности "облачных" вычислений значительно превосходить мощности доступных компьютеров в доме. В этом смысле вся нами обсуждаемая "экономия" своего рода предрассудки.


2011-09-07 12:21:24 | Андрей
Поправьте если не так. Это получается, что мы гуглу всё время посылаем флаковый файл, а комп реагирует только на нужную фразу когда она придёт?
Если так, нельзя ли заставить комп отправлять звуковое сообщение только когда нам это надо? Например: "Дядя Вася, включи свет", после слов Дядя Вася копьютер записал файл с командой, отправил гуглу, тот ему перевод, и он его исполнил. А потом опять в режим ожидания пока не позовут?


2011-08-01 11:03:16 | Andrey_B
Антон, это означает, что в переменной $result, которая заполняется функцией curl_exec(), содержится совсем не то, что нужно.
Посмотрите содержимое архива $json_array. Все сразу станет ясно.


2011-07-31 23:18:16 | anton
сорри вот 25 строка

$voice_cmd = $json_array["hypotheses"][0]["utterance"];


2011-07-31 23:15:49 | anton
У меня скрипт выдает в окно терминала такую ошибку

PHP Notice: Undefined offset: 0 in /home/anton/texttocmd.php on line 25


на 25 строчке находится вот что

$json_array = json_decode($result, true);

где искать ошибку?


2011-07-28 11:31:59 | Andrey_B
Юрий, Гугл знает не только то, что вы ищите, но и на каких сайтах бываете, какие страницы просматриваете. Он, судя по вашему емейлу, знает содержание всех ваших писем, с кем вы общаетесь и что конкретно пишите, какими товарами и услугами интересуетесь. Видит не только текст, но и фотографии, которые вы пересылаете. И это еще вопрос - где содержится более приватная для конкретного человека информация - в разговорах с женой и детьми или в его письмах любовнице. ;)
Мир движется по пути хранения и обработки всей информации в сети, которая в принципе, по своей сути публична. Это и не хорошо и не плохо. Это естественный сценарий развития информационного общества.
Раньше были люди, которые, избегая прогресса, уходили в леса и жили общинами, полностью изолированными от мира. Уходить ли в информационную изоляцию - решать вам. ;)


2011-07-28 10:56:31 | Юрий
Не сочтите параноиком ;-) Но гугл теперь будет знать не только о том, что вы ищете в сети, но и о том, что вы ГОВОРИТЕ дома.


2011-05-13 18:07:06 | Andrey_B
Дмитрий, по вашему вопросу на форуме сайта создана тема. По существу темы - вопрос ваш открытый, требует экспериментов, испытаний, анализа. Готового решения предложить не могу, а сам этой темой более плотно займусь, наверное, ближе к осени.


2011-05-13 13:39:50 | Дмитрий
день добрый!
вопрос по микрофону
какой лучше поставить на комнату 3х4 метра что бы ловил речь чётко
и не приходилось орать в определённую сторону, стоя в определённом месте ?
и куда поставить ?
в потолок, в стену или несколько нужно устанавливать и потом каким то образом сводить воедино..


2011-05-07 15:35:47 | debian user
>Intel HDA Audio и вы счастливый пользователь Debian...что микрофон у вас не работает и что его вообще нет в микшере

это проще лечится - аптом alsa-utils, запуском alsamixer'а и выправлением всех "00" и "ММ" на ползунках. альсу при этом настраивать не обязательно