Русский
Русский
English
Статистика
Реклама

Pocketsphinx

Я сделаю свою умную колонку with blackjack and hookers!

23.01.2021 22:04:46 | Автор: admin

Привет всем. В данной статье я расскажу историю как мы с двоюродным братом сделали свою умную колонку.

На самом деле никакая она неумная, грубая и не особо полезная, но зато весёлая и с характером.

За мной сама идея, программирование, железо (подбор и настройка).

От брата 3D-модель, 3D-печать, железо (подбор и электромонтаж).

Статья по-большей части описывает то, что делал я, лишь немного касаясь 3D-модели.

"Ты на самом деле хочешь дружить с роботом?"

Будучи большим фанатом известного мультсериала Футурама, однажды (где-то в 2018 году)мне захотелось заиметь самодельную голову робота Бендера Родригеса. В голове, в том числе крутились дурацкие варианты сделать её из какой-нибудь кастрюли. В силу своей глупости идея была забыта и заброшена ровно до того момента пока у одного хорошего человека, моего брата, товарища xbostа не появился 3D-принтер (весна 2019 года). И тут эта идея снова ожила

Обсудив эту идею за пивом, принялись за работу. Брат начал делать 3D-модель, а я искать, что из электронного хлама в ящике стола можно задействовать в проекте.

К тому моменту, у меня уже несколько лет валялась без дела плата Intel Galileo Gen2. И было желание задействовать её в этом проекте. Изначально никаких умных функций не планировалась, просто запихнуть её в корпус вместе с динамиком и светодиодами, вытащить кнопочку, при нажатии на которую воспроизводились бы цитаты из серий и светились диоды.

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

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

Первые попытки

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

В силу своей природной хм невнимательности, я упустил существование более подходящей для моей задачи версии pocketsphinx, и начал с большого CMU Sphinx на Java.

Создал простенькие JSGF-грамматику и программу на Яве. Взял несколько наиболее известных цитат для проигрывания(with blackjack and hookers, bite my shiny metal ass, kill all humans и т.п.). Пробовал изначально на достаточно мощном компьютере(MacBook Pro 13-го года), был доволен результатом производительности, но понимал, что на Галилео меня ждёт нечто другое. Но дело оказалось совсем плохо.

Вообще Галилео уже давно заброшен Интелом. Стандартный Линукс, шедший с ним мне в принципе особенно не нравился. Поэтому попробовал с последней доступной для него сборкой Дебиан.

Туда с проблемами(подробности уже честно не вспомню) был поставлен JRE. В качестве устройства ввода/вывода аудио была использована USB-гарнитура. И Результат был крайне печален в плане производительности. Сейчас опять же не вспомню, возможно неправильную акустическую модель использовал на ней, но на реакции уходило 30-60 секунд. Плюс брат начал разрабатывать 3D-модель, и сказал, что габариты Галилео большеваты. Плюс отсутствие встроенного Wi-Fi. В общем Галилео опять отправилась в стол.

Решено было попробовать на гораздо более популярной Малинке, и выбор пал на слабую, но самую компактную версию Raspberry Pi Zero W. А также, прокачав внимательность, узнал о pocketsphinx (отличная статья для старта), перешёл на него, и переписал программу на Питоне.

При переходе на Малину, с подачи xbostа, родилось название для проекта Pinder (Raspberry Pi + Bender). Да, я прекрасно помню историю с Pidora в русскоязычном сегменте, но в данном случае намеренно выбрал такое лулзовое для русского уха название.

И так предыстория завершена, можно переходить непосредственно к описанию Пиндера.

Внутренняя железная часть

Перечень использованных компонентов:

  • Raspberry Pi Zero W собственно основа всего.

  • UPS-Lite for Raspberry Pi Zero

    Маленький ИБП для Малинки. Его штатный выключатель был выпаян, и к его контактам был припаян микропереключатель (см. далее по списку).

  • RGB адресная светодиодная лента на WS2812B, 60 светодиодов на 1 метр

    Для подсветки и анимации зубов(18 штук) и глаз(2 штуки).

  • USB-аудиокарта

    В принципе подойдёт любая, работающая в Линуксе. Подключается через OTG-кабель в единственный доступный для этого порт на Малине Зеро.

  • Усилитель и один динамик от таких колонок

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

  • Микрофон HBC10A

    Но во время разработки поначалу использовался микрофон от телефонной гарнитуры Philips.

  • Микропереключатель с лапкой KLS7-KW10

    Замыкается/размыкается при вставлении/вынимании "антенны" Бендера. Включает/выключает питание от UPS к Малине.

  • 3,5мм разъём и гнездо jack. Для подключения микрофона к аудиокарте (микрофон находится наверху Бендера, в антенне).

В общем внутри всё достаточно колхозно.

Схема подключений очень простая:

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

3D-модель, корпус

Здесь я не смогу рассказать многого, так как эта часть работы полностью брата.

3D-модель и небольшая инструкция доступны здесь.

Зубы и глаза напечатаны фотополимерной смолой на Anycubic Photon. Все остальные части PLA на Creality Ender 3.

Если будут какие-то вопросы по 3D-модели и печати можно задать мне, я их передам, либо попробовать напрямую спросить у xbostа на thingiverse (но не уверен будет ли он на них отвечать).

Краткая схема сборки:

Фото

Фото в процессе сборки и полностью собранном виде:

Программная часть 1

В качестве ОС используется штатный Raspbian (теперь Raspberry Pi OS).

За распознавание, как уже писалось выше, отвечает pocketsphinx. В качестве аудиоподсистемы используется Alsa (Pulseaudio выпилен).

Подсветка управляется с помощью библиотеки Adafruit_Blinka.

Данные о заряде/напряжении читаются из UPS-Lite посредством SMBus.

При разработке никакими лучшими практиками не руководствовался, поэтому код попахивает.

Код лежит здесь.

Поддерживается два языка: английский и русский. Для каждого языка своя JSGF-грамматика, набор аудио-сэмплов(сэмплов в репозитории нет, по соображениям авторских прав) и синтез речи. Русский дорабатывался(и дорабатывается) с некоторым опозданием.

Основной целью была просто возможность отвечать фановыми фразами из серий. Задаешь ему вопросы типа Как дела?, Где ты родился?, Что думаешь о Сири?. Ищется и воспроизводится ответ из сэмплов (в случае отсутствия сэмпла используется синтез речи, но об этом чуть позже).

Изначально скорость ответов на Малине была не очень шустрой (4-6 секунд до ответа):

Покопавшись у себя в коде, были найдены и уничтожены необязательные паузы. То же самое касалось и сэмплов (были пустые места вплоть до 1 секунды в начале файлов). А также прочитана информация о параметрах оптимизации pocketsphinx. Получилось уже получше:

Далее начал добавлять кое-какие полезные функции. Первой стала проигрывание музыки с локальной ФС или интернет-радио с помощью MPD. При этом докричаться до Бендера при проигрывании музыки на приличной громкости сложновато:

После достаточно долгого перерыва, живя на даче, была добавлена первая функция умного дома- управление освещением в своём углу через ModBusTCP. Вот только Бендера недостаточно иногда просто попросить включить свет, нужно обязательно сказать "пожалуйста". Работает достаточно шустро:

Программная часть 2

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

Почитав информацию и попробовав разные варианты остановился на Microsoft Azure Custom Speech.

При создании пользовательского голоса на выбор есть три варианта:

  • Statistical Parametric стандартное качество, нужно небольшое количество(для английского языка) сэмплов для обучения.

  • Concatenative высокое качество, нужно 6000 сэмплов для обучения.

  • Neural премиум-качество. По факту недоступно(доступно из США, при написании челобитной в Майкрософт зачем тебе это нужно и выкладывании 100000$).

Более подробно по технологиям синтеза речи можно почитать например на Википедии.

У меня не было большого количества сэмплов, поэтому сначала поигрался со Statistical Parametric. Результат был неплох, голос конечно не был похож(такой тип синтеза для сильной похожести и не предназначен), но интонации передавал сносно. В итоге на основе набора данных созданного с помощью этой модели я создал оффлайновую модель для CMU Flite, используемую в случае отсутствия связи с MS Azure.

Но всё же хотелось большей похожести и я решился попробовать собрать 6000 сэмплов для Concatenative модели, использующей отрывки из сэмплов настоящего голоса. Очень помог некий хороший человек, выложивший на YouTube 7 видео The Best of Bender. Надёргав оттуда сэмплов, приплюсовав к ним те что уже были и натравив на них майкрософтовский же Text-to-Speech (здесь у меня набор тулзов вспомогательных), получил что-то около 2000 транскрибированных сэмплов. Было принято решение просто скопировать это всё три раза под разными именами, чтобы получить 6000.

В итоге всё это было залито на обучение модели, и результат получился следующим:

Да конечно не идеально, но меня результат трудов устроил.

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

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

Будущее

Как таковых планов развития проекта нет. Если появляется желание и вдохновение, то добавляю что-нибудь. Так конечно напрашивается сделать режим просто болталки на нейронке, обученной на фразах Бендера. Ещё возможно добавить режим bluetooth-колонки(и чтобы зубы загорались синим в этом режиме) и приложение для смартфона, для активации схемы патриотизма.

Но для начала надо изобрести удлинитель пальца.

Заключение

Исходный код ПО и 3D-модель выложены под открытыми лицензиями, так что если у кого-то есть желание сделать своего Бендера, добавить свои функции и улучшить буду рад.

На этом статья подошла к концу. Спасибо, что прочитали!

Всем хороших новостей!

Подробнее..

Как мы обучили сфинкса для голосового помощника

09.07.2020 12:23:49 | Автор: admin
В процессе разработки проекта голосовой помощник одним из требований была возможность распознавания управляющих команд в оффлайн режиме. Это было нужно, так как в противном случае пришлось бы постоянно слушать и посылать поток с аудиоданными на распознавание, получать ответ и анализировать его.

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



Что случилось


Изначально Pocketsphinx работал у нас на железе OrangePi, у которого были: RAM 512Mb, несколько ГБ свободного дискового пространства, а на борту крутилась Ubuntu. При этом мы использовали python интерфейс (в виде python пакета) для работы с Pocketsphinx.

Мы установили Pocketsphinx командой

`pip install pocketsphinx`

Python позволил использовать нам имеющиеся библиотеки и повысить скорость разработки кода. Однако, даже один только процесс потреблял порядка 30-40 Мб оперативной памяти.

Это могло стать проблемой, потому что выяснилось, что доступное по цене железо заметно скромнее: для операционной системы доступно 123 из 128 Мб RAM, часть которой отводится под нужды железа. Из них часть памяти уже использовалась ОС Linux. Для нашего ПО оставалось только 62 Мб RAM и несколько десятков Мб свободной флеш памяти для хранения кода и файлов. Нужно было искать альтернативу python.

Решили запустить часть с Pocketsphinx на Си.

Сборка Pocketsphinx на Си


Исходники для Pocketsphinx были взяты с сайта: cmusphinx.github.io

Для работы Pocketsphinx требуются обе части Sphinxbase и Pocketsphinx. Далее нужно было понять как кросс-компилировать имеющиеся исходники компилятором для нашей целевой аппаратной платформы.

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

`--without-python`

В результате мы получили инструментарий, в котором есть библиотеки для работы с Pocketsphinx. Он находятся по пути

`sphinx/lib`

Для дальнейшей работы с Си кодом требуются библиотеки:

`libpocketsphinx.so libsphinxbase.so libsphinxad.so`

Нюансы


После запуска Pocketsphinx с использованием библиотек оказалось, что Си вариант гораздо менее требователен к ресурсам. Использование RAM сводилось буквально к нескольким Mb.

Приложение после запуска занимало не более 5Mb RAM, но в нем при этом использовались еще с десяток других модулей и ряд библиотек. Если в варианте с python загрузка ядра CPU была весьма заметной (50% или даже более), то тут загрузка ядра была 7-9% (и это на все приложение, а не только на Pocketsphinx).

В процессе работы нами было замечено, что Pocketsphinx начинает определять ключевое слово не сразу, а через некоторое время (от нескольких десятков секунд до пары минут). Начался новый этап работы.

Работа с Pocketsphinx


Работа с Pocketsphinx состоит из этапов:

  1. Подготовка записей в соответствии с текущей задачей.
  2. Подготовка базы данных для модели.
  3. Построение языковой модели: обучение модели на полученных записях. Получение Pocketsphinx model and language model.
  4. Реализация алгоритма использования API Pocketsphinx.
  5. Поиск оптимальных параметров Pocketsphinx эмпирическим методом.

Остановимся на каждом этапе подробнее.

1. Подготовка записей в соответствии с текущей задачей


Подготовить базу записей в формате PCM.

Мы использовали следующие настройки:

Format settings, Endianness: Little
Bit rate: 256 Kbps
Channel(s): 1 channel
Sampling rate: 16.0 KHz
Bit depth: 16 bits

В специальном помещении для записи голоса они произносили ряд слов, каждый в нескольких интонациях (удивление, злость, грусть) и частотах (громко, тихо, нормально). Было сделано 100 записей: 60 мужских и 40 женских.

Примечание: для изменения частоты дискретизации используйте инструмент sox: sox original.wav -b 16 sample.wav каналов 1 скорость 16.

2. Подготовка базы данных для модели


etc
your_db.dic (Phonetic dictionary)
your_db.phone (Phoneset file)
your_db.jsgf (Language grammer)
your_db.filler (List of fillers)
your_db_train.fileids (List of files for training)
your_db_train.transcription (Transcription for training)
your_db_test.fileids (List of files for testing)
your_db_test.transcription (Transcription for testing)
wav
speaker_1
file_1.wav (Recording of speech utterance)
speaker_2
file_2.wav

3. Построение языковой модели


  1. Подготовить базу данных;
  2. Создать учебные файлы и полный словарь и список слов;
  3. Создать словарь из ru.dic и wordlist;
  4. Создайте файл из ru.dic;
  5. Извлечь текст из файла транскрипции;
  6. Построить языковую модель. Скачать инструмент SRILM и создать пакет для построения модели.
  7. Конвертировать файлы lm в файлы dmp.

    sphinx_lm_convert -i model.lm -o model.dmpsphinx_lm_convert -i model.dmp -ifmt dmp -o model.lm -ofmt arpasphinx_lm_convert -i model.lm -o model.lm.binsphinx_lm_convert -i model.lm.bin -ifmt bin -o model.lm -ofmt arpa
    
  8. И, наконец, обучить модель на полученных записях.

Шаги обучения


После подготовки файлов мы должны сгенерировать файл конфигурации: из корневой папки модели мы запускаем:
sphinxtrain -t setup "имя модели"

в конфигурационном файле sphinx_train.cfg:

1- set the value current to the variable CFG_CMN         $CFG_CMN = 'current';2 -$CFG_INITIAL_NUM_DENSITIES = 256; change this value to 13- $CFG_FINAL_NUM_DENSITIES = 256; change this value to 84- $CFG_N_TIED_STATES = 200;  set this value to 200$CFG_CD_TRAIN = 'yes'; set this value to no if the data set is small

Примечание: если мы изменим

$ CFG_CD_TRAIN

на нет, то нам нужно изменить

$ DEC_CFG_MODEL_NAME

на

$ CFG_EXPTNAME.ci_cont

из вашего sphinx_train.cfg. Изменить можно так:

$ DEC_CFG_MODEL_NAME = "$ CFG_EXPTNAME.ci_cont";

или

$ DEC_CFG_MODEL_NAME = "$ CFG_EXPTNAME.ci _ $ {CFG_DIRLABEL}";

Последний шаг начать тренировки нашей модели: sphinxtrain run.

Языковую модель возможно создать с нуля при помощи Sphinxtrain или можно использовать готовую из источника.

Инструкция по создании модули с нуля можно найти на github.

4. Реализация алгоритма использования API Pocketsphinx


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

  1. Распознавание речи в записаном аудио файле;
  2. Распознавание речи в потоке данных от микрофона.

Обобщенный алгоритм взаимодействия с Pocketsphinx после инициализации необходимых ресурсов:

1. Начать распознавание речи:

`int ps_start_utt(ps_decoder_t *ps)`

2. Передать данные из входного потока в Pocketsphinx:

`int ps_process_raw(ps_decoder_t *ps, int16 const *data, size_t n_samples, int no_search, int full_utt)`

3. Закончить распознавание речи:

`int ps_end_utt(ps_decoder_t *ps)`

4. Получить результат распознавания в виде строки:

`char const *ps_get_hyp(ps_decoder_t *ps, int32 *out_best_score)`

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

```Cfor (;;) {    if ((k = ad_read(ad, adbuf, 2048)) < 0)        E_FATAL("Failed to read audio\n");    ps_process_raw(ps, adbuf, k, FALSE, FALSE);    in_speech = ps_get_in_speech(ps);    if (in_speech && !utt_started) {        utt_started = TRUE;        E_INFO("Listening...\n");    }    if (!in_speech && utt_started) {        /* speech -> silence transition, time to start new utterance  */        ps_end_utt(ps);        hyp = ps_get_hyp(ps, NULL );        if (hyp != NULL) {            printf("%s\n", hyp);            fflush(stdout);        }        if (ps_start_utt(ps) < 0)            E_FATAL("Failed to start utterance\n");        utt_started = FALSE;        E_INFO("Ready....\n");    }    sleep_msec(100);}```

Подробный пример взаимодействия с API Pocketsphinx, при чтении данных из файла:

```Cwhile ((k = fread(adbuf, sizeof(int16), 2048, rawfd)) > 0) {    ps_process_raw(ps, adbuf, k, FALSE, FALSE);    in_speech = ps_get_in_speech(ps);    if (in_speech && !utt_started) {        utt_started = TRUE;    }     if (!in_speech && utt_started) {        ps_end_utt(ps);        hyp = ps_get_hyp(ps, NULL);        if (hyp != NULL)    printf("%s\n", hyp);        fflush(stdout);        ps_start_utt(ps);        utt_started = FALSE;    }}```

5. Поиск оптимальных параметров Pocketsphinx эмпирическим методом


После создания или скачивая языковой модели в файлах модели возможно найти файл feat.params. Данный файл необходим для задания параметров работы Pocketshinx. Если параметра нет в данном файле, то используется значение по умолчанию, список всех параметров и их описание возможно найти в исходном коде проекта или на сайте mankier.

Пример вывода программы pocketsphinx_continuous при использовании языковой модели.

```$ pocketsphinx_continuous -samprate 8000 -lm ru.lm -dict ru.dic -hmm zero_ru.cd_cont_4000 -remove_noise no -infile decoder-test.wavINFO: pocketsphinx.c(152): Parsed model-specific feature parameters from zero_ru.cd_cont_4000/feat.paramsCurrent configuration:



```

Распознавание из аудио файла или из данных микрофона определяется ключами:

`-infile <file-name>` и `-inmic <yes/no>`

соответственно.

Ключ файл языковой модели:

`-lm ru.lm`

Файл словаря:

`-dict ru.dic`

Путь, где хранятся файлы внутренней кухни Pocketsphinx:

`-hmm zero_ru.cd_cont_4000`

также файл feat.params.

Существует возможность распознавать в речи только часть слов языковой модели. Функцию включает ключ:

`-kws <file-name.txt>`

Например, наш файл с ключевой фразой выглядит так:

```окей скай /1e-15/```

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

Итог


Краткая версия для спешащих: мы использовали Pocketsphinx на python, но потом эту стратегию пришлось изменить из-за ограничений памяти на железе. Мы выбрали язык Си. Столкнулись с некоторыми нюансами:

Сборка не проходила с первого раза, а чаще всего со второго;
Ключевое слово определялось не сразу: от нескольких долей секунд до нескольких минут.

Работа с Pocketsphinx состоит из этапов:

  1. Подготовка записей в соответствии с текущей задачей.
  2. Подготовка базы данных для модели.
  3. Построение языковой модели: обучение модели на полученных записях. Получение Pocketsphinx model and language model.
  4. Реализация алгоритма использования API Pocketsphinx.
  5. Поиск оптимальных параметров Pocketsphinx эмпирическим методом.

Сейчас мы собираем все вместе.
Подробнее..

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru