Микрофон и распознавание речи на raspberry pi

  • Автор
Ранее было описано как настроить синтезаторы речи festival и espeak на rasberry pi.
http://raspberrypi.ru/blog/readblog/153.html
Сейчас я хочу описать, как преобразовать речь человека , а затем обработать полученные данные.

Хочу сразу заметить , что ни одно готовое решение для Linux найденное в интернете у меня сразу не заработало, все настраивалось экспериментально. Как известно, raspberry pi не имеет входа для микрофона, но это не проблема поскольку можно подключить usb микрофон. Как всегда в магазине микрофона не оказалось и я взял usb камеру со встроенным микрофоном Microsoft VX-800, которая входит в список поддерживаемых устройств на сайте производителя. Начинаем подключать. Для начала надо установить некоторые пакеты, делаем:

#apt-get install v4l-utils sox alsa-tools alsa-oss flac


Запускаем :
#lsusb        
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 002: ID 0424:9512 Standard Microsystems Corp.
Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp.
Bus 001 Device 004: ID 045e:0766 Microsoft Corp.
Bus 001 Device 005: ID 2341:0043 Arduino SA Uno R3 (CDC ACM)


Наша камера: Bus 001 Device 004: ID 045e:0766 Microsoft Corp.

 Камеру увидели, хорошо.    
#v4l2-ctl --all
Driver Info (not using libv4l2):
Driver name : uvcvideo
Card type : Microsoft LifeCam VX-800
Bus info : usb-bcm2708_usb-1.2
Driver version: 3.2.27
Capabilities : 0x04000001
Width/Height : 640/480
Pixel Format : 'YUYV'
Field : None
Bytes per Line: 1280
Size Image : 614400
Colorspace : Unknown (00000000)
Crop Capability Video Capture:
Bounds : Left 0, Top 0, Width 640, Height 480
Default : Left 0, Top 0, Width 640, Height 480
Pixel Aspect: 1/1
Video input : 0 (Camera 1: ok)
Streaming Parameters Video Capture:
Capabilities : timeperframe
Frames per second: 30.000 (30/1)
Read buffers : 0


Ну здесь вроде бы все про видео камеру, много всякой информации. Проверяю номер устройства для записи.
 #arecord -l      
**** List of CAPTURE Hardware Devices ****
card 1: VX800 [Microsoft LifeCam VX-800], device 0: USB Audio [USB Audio]
Subdevices: 1/1 Subdevice #0: subdevice #0 Ну вроде наш микрофон 1,0

Еще можно посмотреть #cat /proc/asound/cards 0 [ALSA ]:
BRCM bcm2835 ALSbcm2835 ALSA - bcm2835 ALSA
bcm2835 ALSA 1 [VX800 ]: USB-Audio - Microsoft LifeCam VX-800
Microsoft Microsoft LifeCam VX-800 at usb-bcm2708_usb-1.2, high speed


И вот теперь начинаются грабли, что хорошо работало в других версиях Linux на РС здесь никак не хочет.
В пакет Sox входять утилиты sox, play и rec, так вот если sox и play запустить получилось, то rec ни в какую микрофон видеть не хочет. Запуск play.
 #export AUDIODEV="hw:0" 
#play test.wav

вот так работает.

Откровенно говоря и не надо , у нас есть arecord. Делаем запись с указанными параметрами, почему именно так - не знаю , но так любит googl.
#arecord -B --buffer-time=1000000 -f dat -r 16000 -d 4 -D plughw:1,0 send.wav

Теперь расшифрую:
-B --buffer-time=1000000 - какой то буфер , о нем описано в --help, если его не ставить то будет ошибка overrun!!!(...) и google не распознает, причем это происходит не всегда, но хочется иметь какую то стабильность.
-f dat - без этой команды пишет 8 бит запись ,а с этой 16 бит
-r -- sample rate 16000 опять же google любит -d 4 -- длительность записи 4 сек , мне хватает чтобы сказать фразу из двух трех слов -D plughw:1,0 -- а это , что называется за что боролись, наш микрофон.
send.wav - файл куда пишем.

Если все правильно , то при запуске на камере загорается светодиод на 4 сек и в этот момент надо что то сказать.
Проверка: #aplay send.wav
Теперь надо преобразовать в формат flac , так любит google, делаем:
#flac -f -s send.wav -o send.flac

Вот теперь у нас два файла send.flac и send.wav , .wav можно удалить.

Теперь с помощью PHP надо отослать этот файл на сервер google для расшифровки. Просто я больше PHP предпочитаю.

$file_to_upload = array('myfile'=>'@./send.flac');   
$ch = curl_init();
// в конце строки надо указать lang=ru-RU или en-US для английского
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_TIMEOUT,15);
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);
echo $result."\n";

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

if(strlen($result) > 3 )
// if coonect and get response
{
$fm_google=substr($result,strpos($result,"utterance")+12,strpos($result,"confidence")-27 - strpos($result,"utterance")+12);
}


кто-то может использовать другой метод ,более эффективный, я буду только рад за подсказку. Теперь полученный ответ кажды может использовать на свое усмотрение , я например использую базу MySQL с набором вопросов и ответов.
Самый простой вариант в РНР:
 system("espeak -ven -s 160 -g 5 \"".$fm_google."\" 2> /dev/null &");

а можно какой то скрипт запустить. Пример. Запускаем скрипт и говорим "сколько время".

  #!/usr/bin/php5      
system("arecord -B --buffer-time=1000000 -f dat -r 16000 -d 4 -D plughw:1,0 send.wav");
system("flac -f -s send.wav -o send.flac");
$file_to_upload = array('myfile'=>'@./send.flac');
$ch = curl_init();
// в конце строки надо указать lang=ru-RU или en-US для английского
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_TIMEOUT,15);
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);
if(strlen($result) > 3 )
// if coonect and get response
{
$fm_google=substr($result,strpos($result,"utterance")+12,strpos($result,"confidence")-27 - strpos($result,"utterance")+12); }
if($fm_google=="сколько время")
{
// указываем скрипт , сообщающий время
system("./gettime.sh");
}


У меня эта связка работает совместно с Arduino UNO и подключенным к нему sound sensor. Происходит все так:
1. Говорю медленно "Артур" (типа R2 по англиски) , запускается скрипт записи и загорается лампочка.
2. Говорю "сколько время" или "который час" (в базе прописаны все подобные варианты)
3. После этого начинается обработка, делаем скидку на плохой интернет (очень тупой 3Г) , медленная реакция файловой системы (может СД карта такая , пока не знаю)
4. Слушаем ответ типа "Босс время в системе ......".

Очень интересно узнать может кто использует другие варианты ?

Комментарии:

admin
Говорить с английским акцентом что-ли надо?
Гугл нормальную русскую речь не понимает?
foxter6
А если подключить sound sensor напрямую к малинке? думаю проблем не должно возникнуть
JackM10
Sound sensor -- выход аналоговый
foxter6
А если прицепить компаратор и включать запись при каком-то уровне ?
JackM10
Откровенно говоря я не пробовал c компаратором.
Время реакции ардуино вполне устраивает, он к тому же передает еще много разных параметров.
ADC на ардуино последовательный имеет 10 бит , это дискретность 1024, sound sensor выдает максимальный уровень 650, программно я подобрал срабатывание типа:
if(Soundsensor > 550) { system("record.sh"); }
Этого достаточно чтобы скрипт срабатывал с расстояния 2-3 метров.
JackM10
С русской речью гугл вроде нормально распознает, только голос сына не хочет понимать.
alex.spb11
Очень интересный пост!
Хочу попробовать прикрутить аналогичное распознование речи. Но в качестве АЦП буду использовать беспроводные приемо-передатчики XRF от Ciseco (дешевый аналог Xbee). Какой sound sensor использовался? И сколько примерно времени уходит от момента произнесения команды до получения строки распознования?
JackM10
Какой сенсор точно сказать не могу ,заказывал через электронщик ., название было Grove - Sound Sensor.
Ардуино висит на скорости 115200 ,довольно быстро работает, поэтому после первого слова включается запись, примерно так:
"робот , как тебя зовут" -- после слова "робот" включается запись.
tubsids3
спасибо за описание!

Вопрос:
Как проводится распознавание? Команды выполнять на ардуино?
зачем конвертирование на гуугле?
crazysova7
Последние строчки я бы использовал так

if(strstr($fm_google,"время")){system("./time.sh");}
if(strstr($fm_google,"вконтакте")){system("opera vk.com");}
sonoleo
Доброго времени суток! Я споткнулся в самом начале.

<Откровенно говоря и не надо, у нас есть arecord. Делаем запись с указанными параметрами, почему именно так — не знаю, но так любит googl.

#arecord -B --buffer-time=1000000 -f dat -r 16000 -d 4 -D plughw:1,0 send.wav>

Эта команда выдает ошибку main:682 нет такого файла или директории. У меня Raspberry Pi 2. Операционка rasbian. Хочу записывать через гуглу. И уж затем обрабатывать и распознавать информацию из текстовых файлов.

Помогите!!! Третью неделю сижу с этой проблемкой.
Canabalt
напишите мне в лс в вк vk.com/daniilsmirnov163.Я прошел весь этот путь и готовлю статью о голосовом управлении

Для написания комментариев необходимо зарегистрироваться