Доброе утро!
Вчера вечером заглянул на Хабр, увидел статью Google translate+Asterisk IVR и у меня волосы зашевелились в подмышках.
Синтез речи, как это просто!
Не нужно собирать Festival и искать для него семплы. Все уже готово, просто и от Google.
Сразу переписал предложенный вариант на свою любимый php и оформил в виде AGI для вызова из Астериска. Хотел чтобы синтез можно было использовать одной строкой в диалпланет, как стандартную команду SayDigits():
Пример использования в extensions.ael:
И сам php код (должен быть /var/lib/asterisk/agi-bin/say.php):
В моем Asterisk основным кодеком является alaw, по этому mp3 конвертирую сразу в alaw.
После 10 минут восторга, я вспомнил, что у Google есть возможность распознавать речь (как в поиске с мобильного телефона). Полазил по интернетам и нашел статью Управление голосом. Распознавание русской речи, где лежит пример на php для распознавания речи средствами Google.
Переписал код в форму AGI и получил (/var/lib/asterisk/agi-bin/voice.php):
Google Speech API принимает звуковые файлы в формате flac и speex, из примера оставил flac.
В переменную ${VOICE} будет установлен распознанный текст.
Общий пример использование в extensions.ael:
Record записывает wav файл максимальной длиной 20 секунд и заканчивает запись после 3 секунд тишины.
Так как это тестовый пример мы прослушиваем сказанное и потом синтезируем распознаный текст.
Что можно сказать, Google — молодцы!
Теперь понятно как чистый Asterisk обучить синтезу и распознаванию речи, без использования Festival и Sphinx.
И если начальство попросит быстро сделать голосовую IVR менюшку, мы сможем удивить!
Добавил
Прочитал коментарий пользователя int80h, прочитал про миграцию с Google Translate API на Bing Translate API и подумал что во всем нужна альтернатива.
Версия 2.0
say.php с возможностью синтеза речи через Microsoft Translator:
Microsoft отдает звук в формате wav (у mp3 качество нулевое) и просит какой-то Bing AppId (взял с сайта microsofttranslator.com, посмотрим сколько проживет).
Качество синтеза мне показалось хуже чем у Google, но ударение в именах ставит более правильно.
Русский текст будет работать только при ru, английский будет всегда, но при ru будет «ломаным».
В тексте работают ударения (' перед гласной) и знаки препинания (например !) меняют интонацию.
PS: Заменил, что распознавание речи может выдавать пустой текст, но при повторной отправке того же файла, все проходит гладко, странно это :-)
Вчера вечером заглянул на Хабр, увидел статью Google translate+Asterisk IVR и у меня волосы зашевелились в подмышках.
Синтез речи, как это просто!
Не нужно собирать Festival и искать для него семплы. Все уже готово, просто и от Google.
Сразу переписал предложенный вариант на свою любимый php и оформил в виде AGI для вызова из Астериска. Хотел чтобы синтез можно было использовать одной строкой в диалпланет, как стандартную команду SayDigits():
Пример использования в extensions.ael:
s => { Answer(); Wait(1); AGI(say.php,"Здравствуйте"); AGI(say.php,"Вас приветствует компания"); AGI(say.php,"Habrahabr!",en); AGI(say.php,"Ваш звонок важен для нас!"); AGI(say.php,"Пожалуйста!"); AGI(say.php,"оставайтесь на линии"); AGI(say.php,"Вам обязательно ответят!"); };
И сам php код (должен быть /var/lib/asterisk/agi-bin/say.php):
#!/usr/bin/php -q <?php $agivars = array(); while (!feof(STDIN)) { $agivar = trim(fgets(STDIN)); if ($agivar === '') break; $agivar = explode(':', $agivar); $agivars[$agivar[0]] = trim($agivar[1]); } extract($agivars); $text = $_SERVER["argv"][1]; if (isset($_SERVER["argv"][2])) $lang = $_SERVER["argv"][2]; else $lang = 'ru'; $md5 = md5($text); $prefix = '/var/lib/asterisk/festivalcache/'; $filename = $prefix.$md5; if (!file_exists($filename.'.alaw')) { $wget = 'wget -U "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5" '; $wget.= '"http://translate.google.com/translate_tts?q='.$text.'&tl='.$lang.'" -O '.$filename.'.mp3'; $ffmpeg = 'ffmpeg -i '.$filename.'.mp3 -ar 8000 -ac 1 -ab 64 '.$filename.'.wav -ar 8000 -ac 1 -ab 64 -f alaw '.$filename.'.alaw -map 0:0 -map 0:0'; $exec = $wget.' && '.$ffmpeg.' && rm '.$filename.'.mp3 '.$filename.'.wav'; exec($exec); } echo 'STREAM FILE "'.$filename.'" ""'."\n"; fgets(STDIN); exit(0); ?>
В моем Asterisk основным кодеком является alaw, по этому mp3 конвертирую сразу в alaw.
После 10 минут восторга, я вспомнил, что у Google есть возможность распознавать речь (как в поиске с мобильного телефона). Полазил по интернетам и нашел статью Управление голосом. Распознавание русской речи, где лежит пример на php для распознавания речи средствами Google.
Переписал код в форму AGI и получил (/var/lib/asterisk/agi-bin/voice.php):
#!/usr/bin/php -q <? $agivars = array(); while (!feof(STDIN)) { $agivar = trim(fgets(STDIN)); if ($agivar === '') break; $agivar = explode(':', $agivar); $agivars[$agivar[0]] = trim($agivar[1]); } extract($agivars); $filename = $_SERVER["argv"][1]; exec('flac -f -s '.$filename.'.wav -o '.$filename.'.flac'); $file_to_upload = array('myfile'=>'@'.$filename.'.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=8000")); curl_setopt($ch, CURLOPT_POSTFIELDS, $file_to_upload); curl_setopt($ch,CURLOPT_RETURNTRANSFER,1); $result=curl_exec ($ch); curl_close ($ch); $json_array = json_decode($result, true); $voice_cmd = $json_array["hypotheses"][0]["utterance"]; unlink($filename.'.flac'); unlink($filename.'.wav'); echo 'SET VARIABLE VOICE "'.$voice_cmd.'"'."\n"; fgets(STDIN); echo 'VERBOSE ("'.$voice_cmd.'")'."\n"; fgets(STDIN); exit(0); ?>
Google Speech API принимает звуковые файлы в формате flac и speex, из примера оставил flac.
В переменную ${VOICE} будет установлен распознанный текст.
Общий пример использование в extensions.ael:
s => { Answer(); Wait(1); AGI(say.php,"Здравствуйте"); AGI(say.php,"Пожалуйста"); AGI(say.php,"Скажите имя сотрудника"); Record(/tmp/${UNIQUEID}.wav,3,20); AGI(say.php,"Вы сказали"); Playback(/tmp/${UNIQUEID}); AGI(voice.php,/tmp/${UNIQUEID}); AGI(say.php,"Система услышала"); AGI(say.php,"${VOICE}"); Hangup(); };
Record записывает wav файл максимальной длиной 20 секунд и заканчивает запись после 3 секунд тишины.
Так как это тестовый пример мы прослушиваем сказанное и потом синтезируем распознаный текст.
Что можно сказать, Google — молодцы!
Теперь понятно как чистый Asterisk обучить синтезу и распознаванию речи, без использования Festival и Sphinx.
И если начальство попросит быстро сделать голосовую IVR менюшку, мы сможем удивить!
Добавил
Прочитал коментарий пользователя int80h, прочитал про миграцию с Google Translate API на Bing Translate API и подумал что во всем нужна альтернатива.
Версия 2.0
say.php с возможностью синтеза речи через Microsoft Translator:
#!/usr/bin/php -q <?php $agivars = array(); while (!feof(STDIN)) { $agivar = trim(fgets(STDIN)); if ($agivar === '') break; $agivar = explode(':', $agivar); $agivars[$agivar[0]] = trim($agivar[1]); } extract($agivars); $text = $_SERVER["argv"][1]; if (isset($_SERVER["argv"][2]) && in_array($_SERVER["argv"][2], array('g','m'))) $voice = $_SERVER["argv"][2]; else $voice = 'g'; if (isset($_SERVER["argv"][3])) $lang = $_SERVER["argv"][3]; else $lang = 'ru'; $md5 = md5($text.$voice.$lang); $prefix = '/var/lib/asterisk/festivalcache/'; $appid = 'T0CQJrrwQ1NcJFlJshEfWTzaI18B4TzVvBKx9CDoLvf8*'; $filename = $prefix.$md5; if (!file_exists($filename.'.alaw')) { if ($voice == 'm') { $ext = '.wav'; exec('wget "http://api.microsofttranslator.com/V2/Http.svc/Speak?language='.$lang.'&format=audio/wav&options=MaxQuality&appid='.$appid.'&text='.$text.'" -O '.$filename.$ext); } else { $ext = '.mp3'; exec('wget -U "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5" "http://translate.google.com/translate_tts?q='.$text.'&tl='.$lang.'" -O '.$filename.$ext); } if (@filesize($filename.$ext) > 0) { exec('ffmpeg -i '.$filename.$ext.' -ar 8000 -ac 1 -ab 64 -f alaw '.$filename.'.alaw -map 0:0'); } unlink($filename.$ext); } if (file_exists($filename.'.alaw')) { echo 'STREAM FILE "'.$filename.'" ""'."\n"; fgets(STDIN); } else { echo 'VERBOSE ("Speech Error!")'."\n"; fgets(STDIN); } exit(0); ?>
Microsoft отдает звук в формате wav (у mp3 качество нулевое) и просит какой-то Bing AppId (взял с сайта microsofttranslator.com, посмотрим сколько проживет).
Качество синтеза мне показалось хуже чем у Google, но ударение в именах ставит более правильно.
AGI(say.php,"Здравствуйте",m); AGI(say.php,"Здравствуйте",${ГОЛОС},${ЯЗЫК}); ${ГОЛОС} - может быть m или g (если опустить = g) ${ЯЗЫК} - ru, en и прочее (если опустить = ru)
Русский текст будет работать только при ru, английский будет всегда, но при ru будет «ломаным».
В тексте работают ударения (' перед гласной) и знаки препинания (например !) меняют интонацию.
PS: Заменил, что распознавание речи может выдавать пустой текст, но при повторной отправке того же файла, все проходит гладко, странно это :-)
