Учим Linux говорить и слушать. Julius + Festival

Издательский дом ООО "Гейм Лэнд" ЖУРНАЛ ХАКЕР 133, ЯНВАРЬ 2010 г.

Говорящий пингвин. Учим Linux говорить и слушать

Евгений Зобнин (zobnin@gmail.com)

Разговаривающие с человеком и выполняющие все его команды компьютеры - неизменный атрибут большинства фантастических фильмов. Человек заходит домой, говорит «Свет», и включается освещение, говорит «Музыка», и начинает играть композиция из любимого плейлиста, а в ответ на команду «Новости» приятный женский голос зачитывает последние вести с валютного фронта. Думаешь, это фантастика? Нет, реальность. И реальность с открытыми исходными текстами.

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

Фестиваль приложений

Синтезирование голоса производится с помощью специальных программ-синтезаторов, таких, например, как festival, espeak, flite (облегченная версия festival), mbrola, freetts, ru_tts и других. Наиболее качественной из них, по общему мнению, считается festival, разрабатываемый сотрудниками многих университетов по всему миру и, что самое главное, оснащенный поддержкой русского языка (правда, не из коробки). Большинство других синтезаторов обладают более низким качеством произношения, и, к тому же, не дружат с русским языком (исключением являются espeak, с гораздо более низким, в сравнении с festival, качеством произношения, и ru_tts, разработанный нашими соотечественниками, но говорящий просто отвратительно).

Поверх синтезатора может функционировать так называемый речевой сервер - демон, который всегда находится в фоне и ждет команд от других приложений. Пользователь или программа могут использовать сокет или сообщения D-BUS для передачи текста речевому серверу, который, в свою очередь, сформирует текстовый файл в правильной кодировке и передаст его синтезатору. Кроме того, речевой сервер может нести ответственность за выбор одного из доступных синтезаторов речи, голоса, передачу данных по сети и т.п. Среди примеров можно привести Speech Dispatcher, MultiSpeech и разработанный для дистрибутива AltLinux VoiceMan.

Чтобы научить комп понимать проговариваемые слова, применяются системы распознавания речи (CMU), наиболее известная и работоспособная из которых носит имя Sphinx (cmusphinx.sourceforge.net). Разработкой этого движка занимается университет Карнеги-Меллона, хотя отдельные доработки также производили сотрудники Массачусетского технологического института и корпорация Sun Microsystems. Качество распознавания «Сфинкса» еще далеко от идеала, он постоянно дает сбои и совершенно не способен разобрать слитную речь. Однако его возможностей вполне достаточно для организации системы исполнения простых голосовых команд, что и демонстрируют такие проекты, как Gnome Voice Control и PerlBox.

Альтернатива Sphinx - движок Julius японского происхождения. По качеству распознавания Julius не уступает Sphinx, однако имеет два изъяна: а) отсутствие хорошей акустической модели для английского языка (для русского более-менее нормальной нет и для Sphinx), что означает гораздо более низкое качество распознавания (в конце статьи я расскажу, как обойти эту проблему), и б) он использует внешний движок генерации акустической модели (обучения) HTK, разрабатываемый под руководством Microsoft в Кэмбридже (а это значит, что движок хоть и открыт, но использовать его можно только в личных целях).

Для систем синтеза и распознавания речи существует масса различных оберток, упрощающих использование. Для Festival можно привести в пример приложение kttsd, для Sphinx это уже не развиваемый PerlBox и созданный в рамках Google Summer Of Code апплет для среды Gnome под названием Gnome Voice Control. Отличная графическая оболочка для Julius - программа Simon, написанная с использованием библиотеки Qt4.

Пингвин! Голос!

Как я говорил выше, лучшей программой синтеза речи является Festival, разрабатываемая в Центре изучения речевых технологий в Эдинбургском университете (Шотландия). Она поддерживает множество различных языков и голосов, может читать текст из файла либо из командной строки и записывать результат синтеза в звуковой файл формата wav, включает в себя плагин для pidgin, проговаривающий входящие сообщения. Недостаток программы только в том, что синтез русской речи она не поддерживает, поэтому для прикручивания такой возможности придется скачивать и устанавливать далеко не самого лучшего качества голос, словари ударений и т.п.
Итак, берем дистрибутив Ubuntu (любой из трех последних версий) и выполняем команду:

$ sudo aptitude install festival speech-tools fetvox-ru

Если же пакета festvox-ru нет в комплекте (он доступен, начиная с версии 9.10), то после завершения установки festival выполняем команду, чтобы получить файлы поддержки русского языка (осторожно, файл большой, ~170 Мб):

$ cd; wget http://download.berlios.de/festlang/msu_ru_nsh_clunits-0.5.tar.bz2

Распаковываем архив в каталог /usr/share/festival/voices/:

$ cd /usr/share/festival/voices/
$ sudo mkdir russian
$ sudo tar -xf ~/msu_ru_nsh_clunits-0.5.tar.bz2

В Ubuntu и некоторых других дистрибутивах Festival может выдать ошибку «Linux: can't open /dev/dsp» при попытке вывода звука, поэтому мы должны настроить программу на использование ALSA. Для этого помещаем в файл ~/.festivalrc строки:

(Parameter.set 'Audio_Command "aplay -q -c 1 -t raw -f s16 -r $SR $FILE")
(Parameter.set 'Audio_Method 'Audio_Command)

Если ты все сделал правильно, то после выполнения следующей команды услышишь несколько «железно-звучащий», булькающий, но вполне понятный голос господина Карлова:

$ echo '(voice_msu_ru_nsh_clunits) (SayText "Привет от пингвина!") (quit)' | festival

Текст должен быть в кодировке UTF-8, поэтому заранее установи локаль ru_RU.UTF-8 в своем дистрибутиве. Также рекомендую внести правки в файл /usr/share/festival/languages.scm, чтобы festival научился автоматически находить русский язык и позволял произносить текст, переданный в качестве аргументов командной строки. Открой languages.scm и добавь в его начало строки:

# vi /usr/share/festival/languages.scm

(define (language_russian)
"(language_russian)
Set up language parameters for Russian."
(set! male1 voice_msu_ru_nsh_clunits)
(male1)
(Parameter.set 'Language 'russian)
)

Перейди к строке «(define(select_language language)» и добавь две строки:

((equal? language 'russian)
(language_russian))

Теперь выполни команду:

$ echo "Привет" | festival --language russian --tts

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

$ festival --language russian -tts file.txt

При запуске в режиме сервера festival открывает порт 1314 для чтения команд. Используя эту особенность, ты можешь создать клиент-серверное ПО для выполнения синтеза речи. Запусти festival в серверном режиме:

$ festival --server &

Вызови telnet:

$ telnet localhost 1314

И запиши команды. Например, если хочешь, чтобы festival произнес указанную тобой фразу на русском языке, запиши:

(voice_msu_ru_nsh_clunits)
(SayText "Привет!")

Если же он должен прочитать файл, то команды будут такими:

(voice_msu_ru_nsh_clunits)
(tts_file "Привет")

Для завершения работы festival набери "(quit)". Чтобы каждый раз не выбирать русский язык самостоятельно, добавь в файл /usr/share/festival/init.scm строки:

;;; Default voice (have to do something cute so autoloads still work)
(eval (list voice_msu_ru_nsh_clunits))

Пингвин! Лежать!

Перед тем, как перейти к установке и настройке системы распознавания речи, давай все же определимся с тем, чего мы хотим добиться. Дело в том, что ни один из открытых движков, будь то Sphinx, Julius или какой-то менее известный проект, не способен на 100% верно разобрать речь, даже если она будет принадлежать актеру с хорошо поставленным голосом. Однако при правильной тренировке программы (которая также включает в себя и подгонку под особенности произношения конкретного человека) ее вполне можно научить корректно распознавать простые двух-словные команды почти в 100% случаев.

И вот здесь нас ждет очень неприятный сюрприз: наиболее известная и распространенная CMU Sphinx (которая, кстати, имеет целых четыре параллельно развиваемых версии, одна из них написана на Java) до сих пор находится в стадии «вечной альфы», пользоваться которой (не говоря уже о тренировке) обычному пользователю довольно затруднительно. Существует, конечно, утилита Gnome Voice Control, существенно упрощающая процесс общения с программой, но работает она только в Gnome. Поэтому мы воспользуемся Julius, который хоть и имеет некоторые проблемы, но очень прост в использовании.

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

$ sudo aptitude install julius

Чтобы научить Julius понимать английский язык, тебе понадобятся файлы акустической модели, содержащие статистическое представление звуков, которые может воспринимать движок. Акустическая модель строится путем обработки звуковых файлов (с начитанными человеком фрагментами текстов) специальными программами (например, из пакета HTK). Наиболее правильно самому наговорить эти фрагменты и, таким образом, научить движок распознавать именно твой голос (в том числе, интонацию и ошибки произношения) и словосочетания, которые нужны именно тебе. Тогда процент правильного распознавания будет стремиться к значению 100. Однако все это сложно, требует определенной подготовки и времени, поэтому пока мы ограничимся акустической моделью, распространяемой с сайта www.voxforge.org. Для этого надо установить пакет julius-voxforge:

$ sudo aptitude install julius-voxforge

Теперь можно приступить к настройке, которая фактически включает в себя только процесс создания словаря: списка слов, который должен уметь распознавать движок, и объяснение того, как эти слова могут между собой сопоставляться. Нужно это для двух целей: во-первых, движок должен знать произношение слов и понимать их, а во-вторых, сократив словарь всего до нескольких фраз, мы значительно повысим качество распознавания. Для простоты возьмем стандартные словари, распространяемые вместе с пакетом julius-voxforge:

$ mkdir ~/julius-grammar
$ cp /usr/share/doc/julius-voxforge/examples/* ~/julius-grammar
$ cd ~/julius-grammar
$ gunzip * 2>&1 | grep -v ignored

Просмотрев файл sample.voca, ты можешь заметить, что он содержит совсем небольшой список слов, таких как call, get, dial и т.д., а также их фонетическое представление (что-то вроде транскрипции), файл sample.grammar содержит правила, в каких комбинациях эти слова могут быть использованы. Не беспокойся, если он тебе непонятен, это нормально.

Попробуем изменить файлы так, чтобы подогнать их под нашу задачу, которой будет… допустим, управление аудиоплеером. Итак, открой файл sample.voca и добавь в него следующее (удалив прежнее содержимое):

$ vi sample.voca

% NS_B
<s>sil

% NS_E
</s>sil

% ID
DOd uw

% COMMAND
PLAYp l ey
NEXTn eh k s t
PREVp r iy v
SILENCEs ay l ax n s

В файл sample.grammar помести строку:

S: NS_B ID COMMAND NS_E

Все это значит, что движок должен понимать словосочетания, которые состоят из: тишина (NS_B), слов «do» (ID), «play», «next», «prev» или «silence» (COMMAND), тишина (NS_E). Говоря проще, ты можешь сказать «Do play», и комп тебя поймет, в то время как слова «Hello World» будут для него инопланетным языком. Хорошая особенность короткого словаря в том, что, даже если ты скажешь что-то вроде «Du pray», движок, скорее всего, распознает это как «Do play», а не как-нибудь иначе (в английском десятки и сотни слов звучат очень похоже).
Теперь, не выходя из каталога, выполни команду для генерации файлов sample.dfa sample.term и sample.dict:

$ mkdfa sample

Это все. Можешь протестировать julius с помощью команды:

$ julius -input mic -C julian.jconf

После появления строки "<<< please speak >>>" начинай говорить определенные выше фразы. Чтобы движок правильно их понял, говори слитно, как это делают англоговорящие (голоса которых и были использованы для создания акустической модели voxforge), без перерыва между словами. То есть, говори «Дуплэй», а не «Ду плэй», словно на занятиях английского для большей разборчивости. При таком способе произношения движок работает на удивление хорошо, лично у меня ни одного сбоя на 10 фраз. Если ты получаешь худшие результаты, хорошенько поработай над своим произношением и купи добротный микрофон.

Конечно, пока от программы мало толку, поэтому мы должны создать Dialog manager, то есть, программу (скрипт), которая будет отвечать за перевод отдаваемых тобой голосовых команд в команды на исполнение. К счастью, сделать это просто, достаточно прицепить на выход Julius стандартный ввод скрипта, который будет обрабатывать печатаемые Julius фразы. Например, скрипт для управления audacious на языке python может выглядеть так:

$ vi command.py

def parse(line):
params = [param.lower() for param in line.split() if param]
commands = {
'play': 'audacious2 -p',
'silence': 'audacious2 -u',
'next': 'audacious2 -f',
'prev': 'audacious2 -r',
}
if params[1] in commands: os.popen(commands[params[1]])

Сохрани его под именем command.py и запускай julius следующим образом:

$ julius -quiet -input mic -C julian.jconf 2>/dev/null | ./command.py

На прилагаемом к журналу диске ты найдешь список фонетических представлений многих английских слов (beep.tar.gz), - их можно использовать для формирования своего собственного словаря. Документы tutorial и how-to на сайте www.voxforge.org описывают процесс создания собственной акустической модели, которую ты сможешь использовать для достижения более высокого качества распознавания (через обучение движка особенностям твоего произношения).

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

Занавес

Открытые системы синтеза и распознавания речи, которые можно использовать в Linux, xBSD, Solaris и других системах, не стоят на месте и продолжают развиваться. Еще совсем недавно мы не имели поддержки русского в festival и не говорили всерьез о распознавании голосовых команд, а сегодня, как ты сам смог убедиться, все это есть и вполне корректно работает. Не без изъянов и подводных камней, со множеством ошибок, но работает.

Два простых скрипта для управления festival

#!/bin/sh
festival -b "(begin (voice_msu_ru_nsh_clunits) (SayText \"$1\" nil))"

#!/bin/sh
festival -b "(begin (voice_msu_ru_nsh_clunits) (tts_file \"$1\" nil))"

Помоги в создании русской языковой модели

Помоги общему делу в создании языковой модели русского языка для Julius и Sphinx. Зайди на страничку www.voxforge.org/ru и в режиме «онлайн» запиши начитанный тобой текст. Проекту нужно всего 140 часов речи для создания качественной языковой модели, однако пока общий объем не достигает и 10 часов.

Sphinx II vs Julius

Ты можешь самостоятельно сравнить качество распознавания Sphinx (второй, самой быстрой версии) и   Julius , просто установив пакет sphinx2-bin:

$ sudo aptitude install sphinx2-bin

И запустив демонстрационную программу распознавания с малым словарем:

$ sphinx2-demo

В моем случае Sphinx показал просто провальные результаты, не идущие ни в какое сравнение с  Julius .

WWW

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

Обратная связь

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

пишите мне на netdm@mail.ru