Доброго вам времени суток.
В данной статье хотелось бы рассмотреть грабли в виде скрипта text2wave из комплекта системы для генерации голоса Festival в FreeBSD. Столкнулся я с этой проблемой при создании голосового меню в Asterisk средствами Festival.
Кому интересно под кат.
Занимаясь, для собственного развития, развертыванием IP-АТС Asterisk, дошел до момента генерации голоса. Учитывая встроенную поддержку Festival и огромное количество инструкций доступных в интернете, взялся за дело. Установил Festival из портов. Скачал и установил русский голос. Накидал менюшку командой Festival(), и, о чудо, все заработало. Вот так вот сходу, как это редко бывает.
Проблема возникла с мобильными клиентами. X-lite на WinCE и встроенный клиент от Nokia упорно не желали рабостать с получившимся меню. Первый рвал сессию сразу, второму удавалось получить пару слогов, после чего и он тоже отваливался.
Непродолжительные поиски указали альтернативу использованию команды Festival() в диалплане. Это был вызов через AGI или через System() скрипта text2wave, сохранение с его помощью файла, а после проигрывание его с помощью комманд Playback() или Background(). Вооружившись парой инструкций я немедленно приступил к действию и тут то и получил граблями.
Думаю, как так… ведь есть же голос, работает нормально…
Присматриваюсь внимательнее, и понимаю, что как то не оттуда цепляет он голоса. Лезу в скрипт и нахожу там чудесную строчку
То есть ссылается он на папку в которой собирался. Ну думаю делов то, и правлю
Запускаем
и обламываемся.
В общем надо отметить, что данную картину я наблюдал большую часть дня. Тащить скрипт из инструкций оказалось более чем бесполезно, во FreeBSD он работать не будет. Равно как и предлагаемый метод запуска Festival в режиме сервера. Так что, все как всегда, берем десяток инструкций и при помощи напильника заставляем рабоать. Впрочем продолжаем.
После довольно продолжительного ковыряния и слепого тыканья, пришло понимание из папки work — работает, из /usr/local/bin — нет.
Простое сравнение показало проблему.
Скрипт запуска и сслыка на исполняемый файл. Результаты естественно разные. Ну что ж, полезем в скрипт.
Мысленно склеиваем скрипты для запуска Festival и для генерации файлов при помощи него text2wave.
Получаем следующую команду
Любые попытки и комбинации двух этих опций приводят к уверенному результату.
Если убрать первый параметр, отваливается голос, если второй голос есть но Festival грузится в обычном интерактивном режиме.
Решение было очевидным, однако реализация так же заняла некоторое время. итогом стала небольшая модификация скрипта text2wave
меняем на
а
меняем на
Вот собственно и все. Теперь можно запускать
Ну и естесствено вызывать, хоть из System() хоть из AGI.
Как и всегда решение оказалось очевидным и простым, достаточно присмотреться.
Постскриптум №1.
В процессе поисков, было обнаружено решение для связки * и Festival, и мэйлинг лист эдинбургского университета.
Это выдержка из мейлинг-листов, перепосченная в десятке мест, очевидно это было лучшее решение которое нашли.
Постскриптум №2.
Для запуска Festival в режиме сервера используется довольно спорная связка со screen.
Выглядит она примерно так:
В данной статье хотелось бы рассмотреть грабли в виде скрипта text2wave из комплекта системы для генерации голоса Festival в FreeBSD. Столкнулся я с этой проблемой при создании голосового меню в Asterisk средствами Festival.
Кому интересно под кат.
Интро
Занимаясь, для собственного развития, развертыванием IP-АТС Asterisk, дошел до момента генерации голоса. Учитывая встроенную поддержку Festival и огромное количество инструкций доступных в интернете, взялся за дело. Установил Festival из портов. Скачал и установил русский голос. Накидал менюшку командой Festival(), и, о чудо, все заработало. Вот так вот сходу, как это редко бывает.
Проблема возникла с мобильными клиентами. X-lite на WinCE и встроенный клиент от Nokia упорно не желали рабостать с получившимся меню. Первый рвал сессию сразу, второму удавалось получить пару слогов, после чего и он тоже отваливался.
Непродолжительные поиски указали альтернативу использованию команды Festival() в диалплане. Это был вызов через AGI или через System() скрипта text2wave, сохранение с его помощью файла, а после проигрывание его с помощью комманд Playback() или Background(). Вооружившись парой инструкций я немедленно приступил к действию и тут то и получил граблями.
[root@AsteriskPV:/usr/local/share/festival/examples]# cp text2wave /usr/local/bin/
[root@AsteriskPV:/usr/local/share/festival/examples]# rehash
[root@AsteriskPV:/usr/local/share/festival/examples]# text2wave
WARNING
No default voice found in ("/usr/ports/audio/festival/work/festival/lib/voices/")
either no voices unpacked or voice-path is wrong
Scheme interpreter will work, but there is no voice to speak with.
WARNING
Грабли
Думаю, как так… ведь есть же голос, работает нормально…
^C
[root@AsteriskPV:/usr/local/share/festival/examples]# text2wave
WARNING
No default voice found in ("/usr/ports/audio/festival/work/festival/lib/voices/")
either no voices unpacked or voice-path is wrong
Scheme interpreter will work, but there is no voice to speak with.
WARNING
Присматриваюсь внимательнее, и понимаю, что как то не оттуда цепляет он голоса. Лезу в скрипт и нахожу там чудесную строчку
#!/bin/sh
"true" ; exec /usr/ports/audio/festival/work/festival/bin/festival --script $0 $*
То есть ссылается он на папку в которой собирался. Ну думаю делов то, и правлю
#!/bin/sh
"true" ; exec /usr/local/bin/festival --script $0 $*
Запускаем
[root@AsteriskPV:/usr/local/share/festival/examples]# text2wave
SIOD ERROR: unbound variable : P▒
и обламываемся.
В общем надо отметить, что данную картину я наблюдал большую часть дня. Тащить скрипт из инструкций оказалось более чем бесполезно, во FreeBSD он работать не будет. Равно как и предлагаемый метод запуска Festival в режиме сервера. Так что, все как всегда, берем десяток инструкций и при помощи напильника заставляем рабоать. Впрочем продолжаем.
После довольно продолжительного ковыряния и слепого тыканья, пришло понимание из папки work — работает, из /usr/local/bin — нет.
Простое сравнение показало проблему.
[root@AsteriskPV:/usr/local/share/festival/examples]# ll /usr/local/bin/festival
-r-xr-xr-x 1 root wheel 132 Nov 24 20:27 /usr/local/bin/festival
[root@AsteriskPV:/usr/local/share/festival/examples]# ll /usr/ports/audio/festival/work/festival/bin/festival
lrwxr-xr-x 1 root wheel 57 Nov 24 20:25 /usr/ports/audio/festival/work/festival/bin/festival -> /usr/ports/audio/festival/work/festival/src/main/festival
Скрипт запуска и сслыка на исполняемый файл. Результаты естественно разные. Ну что ж, полезем в скрипт.
[root@AsteriskPV:/usr/local/share/festival/examples]# cat /usr/local/bin/festival
#!/bin/sh
# path for audsp
PATH=/usr/local/libexec:$PATH
export PATH
exec festival.naked --libdir /usr/local/share/festival/lib $*
Мысленно склеиваем скрипты для запуска Festival и для генерации файлов при помощи него text2wave.
Получаем следующую команду
/usr/local/libexec/festival.naked --libdir /usr/local/share/festival/lib $* --script $0 $*
Любые попытки и комбинации двух этих опций приводят к уверенному результату.
[root@AsteriskPV:/usr/local/share/festival/examples]# /usr/local/libexec/festival.naked --libdir /usr/local/share/festival/lib --script text2wave $*
SIOD ERROR: unbound variable : P▒
Если убрать первый параметр, отваливается голос, если второй голос есть но Festival грузится в обычном интерактивном режиме.
Решение
Решение было очевидным, однако реализация так же заняла некоторое время. итогом стала небольшая модификация скрипта text2wave
"true" ; exec /usr/ports/audio/festival/work/festival/bin/festival --script $0 $*
меняем на
"true" ; exec /usr/local/libexec/festival.naked --script /usr/local/bin/text2wave $*
а
(load (path-append libdir "init.scm"))
меняем на
(set! libdir '/usr/local/share/festival/lib)
(load (path-append libdir "init.scm"))
Вот собственно и все. Теперь можно запускать
echo 123 | text2wave -o 123.ulaw -otype ulaw -
Ну и естесствено вызывать, хоть из System() хоть из AGI.
Как и всегда решение оказалось очевидным и простым, достаточно присмотреться.
Постскриптум №1.
В процессе поисков, было обнаружено решение для связки * и Festival, и мэйлинг лист эдинбургского университета.
Это выдержка из мейлинг-листов, перепосченная в десятке мест, очевидно это было лучшее решение которое нашли.
(Parameter.set 'Audio_Method 'Audio_Command)
(Parameter.set 'Audio_Required_Rate 11025)
(Parameter.set 'Audio_Required_Format 'riff)
(Parameter.set 'Audio_Command "lame --quiet --preset voice $FILE - >> $HOME/festival-output.mp3")
Постскриптум №2.
Для запуска Festival в режиме сервера используется довольно спорная связка со screen.
Выглядит она примерно так:
[root@SIP:/home/admin]# cat /usr/local/etc/rc.d/festival
#!/bin/sh
. /etc/rc.subr
name="festival"
start_cmd="${name}_start"
stop_cmd=":"
festival_start()
{
screen -d -m -s /usr/local/etc/festivalst.sh
}
festival_stop()
{
killall festival.naked
killall screen
}
festival_restart()
{
killall festival.naked
killall screen
screen -d -m -s /usr/local/etc/festivalst.sh
}
#load_rc_config $name
run_rc_command "$1"
[root@SIP:/home/admin]# cat /usr/local/etc/festivalst.sh
festival --server