Google translate+Asterisk IVR

    Долго думал в какой блог запостить и решил, что здесь ему наиболее подходящее место. Хотя бы потому, что основная идея топика «sh — может все».

    В этом топике задали интересную тему — реализовать IVR для * с использованием синтезатора из Google Translate.

    Я в общем то даже не планировал этим заниматься, но мне стало интересно.


    И первое чем я занялся я полез выяснять как же разговаривает Гугл. Говорит хорошо, но только 100 символов. Впрочем этого вполне достаточно для создания IVR. Довольный первым результатом я пустился на поиски того как бы этот голосок подрезать. Недолгие поиски вывели меня на вариант translate.google.com/translate_tts?q=Текст&tl=ru
    Ткнулся с ним в браузер и получил mp3 с произнесенным текстом. Еще больше вдохновленный я засунул эту строчку в wget.

    [utfadm@SIP:/var/lib/asterisk]> wget "http://translate.google.com/translate_tts?q=текст&tl=ru"
    --2011-12-01 13:24:53-- translate.google.com/translate_tts?q=%D1%82%D0%B5%D0%BA%D1%81%D1%82&tl=ru
    Распознаётся translate.google.com (translate.google.com)... 173.194.32.225, 173.194.32.234, 173.194.32.235, ...
    Подключение к translate.google.com (translate.google.com)|173.194.32.225|:80... соединение установлено.
    HTTP-запрос отправлен. Ожидание ответа... 403 Forbidden
    2011-12-01 13:24:53 ОШИБКА 403: Forbidden.

    --2011-12-01 13:24:53-- translate.google.com/translate_tts?q=%D1%82%D0%B5%D0%BA%D1%81%D1%82&tl=ru
    Повторное использование соединения с translate.google.com:80.
    HTTP-запрос отправлен. Ожидание ответа... 403 Forbidden
    2011-12-01 13:24:53 ОШИБКА 403: Forbidden.


    Тут то и ждал меня первый облом. Впрочем немного поразмыслив подумалось, что в корпорации добра люди не глупые и так просто отдавать wget mp3шечки они не будут. Но ведь браузеру отдают…

    Значит замаскируемся под браузер.

    [utfadm@SIP:/tmp]> wget -U "Lynx 1.2.3.4" "http://translate.google.com/translate_tts?q=текст&tl=ru"
    --2011-12-01 13:27:22-- translate.google.com/translate_tts?q=%D1%82%D0%B5%D0%BA%D1%81%D1%82&tl=ru
    Распознаётся translate.google.com (translate.google.com)... 74.125.232.1, 74.125.232.10, 74.125.232.11, ...
    Подключение к translate.google.com (translate.google.com)|74.125.232.1|:80... соединение установлено.
    HTTP-запрос отправлен. Ожидание ответа... 200 OK
    Длина: 0 [audio/mpeg]
    Сохранение в каталог: ««translate_tts?q=\321%82ек\321%81\321%82&tl=ru»».

    [ <=> ] 0 --.-K/s за 0s

    2011-12-01 13:27:22 (0,00 B/s) - «translate_tts?q=\321%82ек\321%81\321%82&tl=ru» saved [0/0]


    Хм… длинна файла получилась нулевой. А если так

    [utfadm@SIP:/tmp]> wget -U "Lynx 1.2.3.4" "http://translate.google.com/translate_tts?q=text&tl=ru"
    --2011-12-01 13:29:59-- translate.google.com/translate_tts?q=text&tl=ru
    Распознаётся translate.google.com (translate.google.com)... 74.125.232.2, 74.125.232.11, 74.125.232.12, ...
    Подключение к translate.google.com (translate.google.com)|74.125.232.2|:80... соединение установлено.
    HTTP-запрос отправлен. Ожидание ответа... 200 OK
    Длина: 4421 (4,3K) [audio/mpeg]
    Сохранение в каталог: ««translate_tts?q=text&tl=ru»».

    100%[===================================================================================================================>] 4 421 --.-K/s за 0s

    2011-12-01 13:29:59 (95,5 MB/s) - «translate_tts?q=text&tl=ru» saved [4421/4421]

    А так работает…

    Думаем, думаем, думаем…
    Может быть русские символы приходящие от lynx не принимаются за русские?
    Тогда сменим user-agent на тот с которым русские буквы точно работают.

    [utfadm@SIP:/tmp]> /usr/local/bin/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=текст&tl=ru"
    --2011-12-01 13:32:27-- translate.google.com/translate_tts?q=%D1%82%D0%B5%D0%BA%D1%81%D1%82&tl=ru
    Распознаётся translate.google.com (translate.google.com)... 173.194.32.225, 173.194.32.234, 173.194.32.235, ...
    Подключение к translate.google.com (translate.google.com)|173.194.32.225|:80... соединение установлено.
    HTTP-запрос отправлен. Ожидание ответа... 200 OK
    Длина: 4421 (4,3K) [audio/mpeg]
    Сохранение в каталог: ««translate_tts?q=\321%82ек\321%81\321%82&tl=ru.1»».

    100%[===================================================================================================================>] 4 421 --.-K/s за 0s

    2011-12-01 13:32:27 (103 MB/s) - «translate_tts?q=\321%82ек\321%81\321%82&tl=ru.1» saved [4421/4421]


    О, уже лучше… только название файла какое то корявеькое
    translate_tts?q=?%82ек?%81?%82&tl=ru.1
    в его исправлении нам поможет ключ -О, и имя будет устанавливаться какое нужно.

    Так, теперь когда мы научились получать файлы с голосом, надо научить это делать *.

    Для этого напишем небольшой скрипт
    #!/bin/sh
    `ls /var/lib/asterisk/festivalcache/$2.gsm`
    if [ $? -eq 1 ]; then
    NAME=/var/lib/asterisk/festivalcache/$2
    /usr/local/bin/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=$1&tl=ru" -O $NAME.mp3
    /usr/local/bin/mpg123 -w "$NAME.wav" "$NAME.mp3"
    echo "Converting from wav to gsm"
    /usr/local/bin/sox -t wav "$NAME.wav" -r 8000 -c1 -t gsm "$NAME.gsm"
    rm $NAME.mp3
    rm $NAME.wav
    fi

    Пробежимся по нему.
    С первой строкой все и так понятно.
    Второй проверяем наличие файла, и если он уже существует то на этом скрипт и заканчивает свою работу.
    Если же нет, то устанавливаем имя файла из второго параметра запуска и полного пути к нему.
    Кидаем гуглу запрос с текстом из первого параметра запуска для сохранения файла в mp3.
    Потом гоним его в wav, потом в gsm.
    Удаляем промежуточные файлы.

    На выходе получаем файл формата gsm который чудесно умеет проигрывать *.

    Ну и собственно пишем в диалплан что нибудь вроде:
    exten => 227,1,Set(home=/var/lib/asterisk/festivalcache)
    exten => 227,2,Wait(1)
    exten => 227,n,System(/bin/sh /var/lib/asterisk/tts.sh ". Здравствуйте" "${EXTEN}.${PRIORITY}")
    exten => 227,n,Playback(${home}/${EXTEN}.$[${PRIORITY} - 1])
    exten => 227,n,Set(tic=${STRFTIME(${EPOCH},,%Y%m%d)}))
    exten => 227,n,System(/bin/sh /var/lib/asterisk/dt.sh 1 "${EXTEN}.${tic}")
    exten => 227,n,Playback(${home}/date/${EXTEN}.${tic})
    exten => 227,n,System(/bin/sh /var/lib/asterisk/tts.sh ". Это меню сформированно при помощи Гугл переводчика" "${EXTEN}.${PRIORITY}")
    exten => 227,n,Playback(${home}/${EXTEN}.$[${PRIORITY} - 1])
    exten => 227,n,System(/bin/sh /var/lib/asterisk/tts.sh ". Досвидания." "${EXTEN}.${PRIORITY}")
    exten => 227,n,Playback(${home}/${EXTEN}.$[${PRIORITY} - 1])
    exten => 227,n,Set(tic=${STRFTIME(${EPOCH},,%H%M%S)})
    exten => 227,n,System(/bin/sh /var/lib/asterisk/dt.sh 2 "${tic}")
    exten => 227,n,Playback(${home}/time/${tic})
    exten => 227,n,Hangup()


    Таким образом при работе скрипта будут сформированы и проиграны файлы 227.3.gsm, 227.8.gsm, 227.10.gsm, и еще два о которых чуть позже. перечисленные файлы буду сгенерированы один раз, потому, что, как мы помним скрипт не исполняется если файл уже существует. Мне кажется что даже 50-60 однажды сгенерированных фраз гугл не обременят, а нам дадут полноценное меню.

    Те два файла о которых я обещал рассказать позже представляют из себя текущие дату и время. Генерируются они и вызываются строками
    exten => 227,n,Set(tic=${STRFTIME(${EPOCH},,%Y%m%d)}))
    exten => 227,n,System(/bin/sh /var/lib/asterisk/dt.sh 1 "${EXTEN}.${tic}")
    exten => 227,n,Playback(${home}/date/${EXTEN}.${tic})


    и
    exten => 227,n,Set(tic=${STRFTIME(${EPOCH},,%H%M%S)})
    exten => 227,n,System(/bin/sh /var/lib/asterisk/dt.sh 2 "${tic}")
    exten => 227,n,Playback(${home}/time/${tic})

    соответсвенно.
    Как видно из вызова обращаются они к другому скрипту. Это обертка для уже рассмотренного скрипта обращения к гуглу за голосом. Выглядит она следующим образом
    #!/bin/sh
    if [ $1 -eq 1 ]; then
    q=`date +"Сегодня %d.%m.%Y года"`
    n=date/$2
    fi
    if [ $1 -eq 2 ]; then
    q=`date +"Точное время %H:%M:%S"`
    n=time/$2
    fi
    echo "$q"
    /var/lib/asterisk/tts.sh "$q" $n

    Все довольно очевидно. Первый параметр определяет получаем ли мы дату или время, второй имя файла. Даты ложатся в папку date время в time. Имя файла нам передает *. tic=${STRFTIME(${EPOCH},,%Y%m%d)}) — это годмесяцдень) и tic=${STRFTIME(${EPOCH},,%H%M%S)} — часминутасекунда. Таким образом если долго не чистить папку time то можно накопить все возможные комбинации.

    Такая вот простенькая оберточка.
    Для генерации коротких фраз любого формата надо всего лишь написать обертку для первого скрипта. Простенько и со вкусом.

    Но у меня была еще задумка читать файлы, но ведь в файле может быть больше 100 символов. Значит придется дробить на несколько запросов. Специфика файлов которые мне необходимо читать такова, что в них много строк, но все они меньше 100 символов. Поэтому я накидал следующий скрипт:
    [root@SIP:/var/lib/asterisk]# cat ttsb.sh
    #!/bin/sh
    Source=/var/lib/asterisk/source
    i=0
    splitted=''
    NAME=/var/lib/asterisk/festivalcache/$2
    `ls /var/lib/asterisk/festivalcache/$2.gsm`
    if [ $? -eq 1 ]; then
    for str in `cat $Source/$1`
    do
    i=`expr $i + 1`
    WORKNAME=/var/lib/asterisk/festivalcache/$2.work.$i.mp3
    splitted="$splitted $WORKNAME"
    #echo $WORKNAME
    #echo $str
    #echo SP: $splitted
    /usr/local/bin/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=$str&tl=ru" -O $WORKNAME
    done
    /usr/local/bin/mpg123 -w "$NAME.wav" $splitted
    echo "Converting from wav to gsm"
    /usr/local/bin/sox -t wav "$NAME.wav" -r 8000 -c1 -t gsm "$NAME.gsm"
    rm $splitted
    rm $NAME.wav
    fi

    Ну тут все тоже достаточно очевидно. Берем файл и каждую его строку скармливаем гуглу, потом все mp3шки склеиваем в один wav, его конвертируем в gsm и удаляем промежуточные файлы. Слышна небольшая пауза, так что хорошо если логически строки подразумевают паузу между их произношением.

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

    В планах наладить сфинкс (видел проект русских грамматик с точностью 96%), результат обработки скармливать гуглу, переводить на другой язык и произносить гуглом же. Пока правда не знаю зачем.

    Similar posts

    Ads
    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More

    Comments 17

      +3
      Спасибо! Однозначно в закладки, может на предприятии и не так часто нужен такой IVR, но вот дома себе сделать умную систему которая умеет голосом зачитывать почту, или ещё какие параметры самое оно.
        0
        Домашний * у меня пока только работает как система громкой связи. Да плюс принимает рабочие звонки, если я не зарегистрирован на рабочей станции. Мысль с чтением почты интересна, надо об этом подумать.
        +2
        Спасибо.
          0
          Всегда пожалуйста.
          +1
          Ярчайший пример интересной и необычной статьи.
            0
            Благодарю. Очень приятно слышать подобный отзыв.
            +1
            Однозначно + за изыскания.
              +1
              Спасибо. Просто мне не нравятся статьи ограничивающиеся сухим остатком — сделайте так, что бы было вот так. Немного рассуждений статью не испортят.
              +5
              Мы на нашей станции ZyXEL x8004 сделали обратное — скармливаем гуглу звуковой файл, он нам выдает текст, мы его берем, лезем во внутреннюю базу, сравниваем текст с текстом ко всем экстеншенам и при совпадении соединяем с нужным абонентом — это самое простое применение распознавания голоса в IVRe.

              применение — теперь если звонит клиент, он может голосом назвать имя сотрудника и произойдет мгновенное соединение (время процедуры — меньше секунды), если такой сотрудник есть в базе — то есть не надо донабор делать (особенно тому, у кого тона вообще нету в телефоне или его неудобно включать).

              вообще, когда гугл ввел распознавание речи, на его основе можно делать любые запросы и создавать технические сценарии в АТС и не только в IVR
                +2
                Ждём статью! ;)
                  0
                  Присоединяюсь, очень интересно будет увидеть как это реализовано.
                    +1
                    Интересен опыт, статья будет?
                      +1
                      Некропостер :)
                      Думаю вряд ли будет статья на эту тему когда-либо.
                      Однако завтра в 11 утра на сайте Ростелекома будет выложен весьма интересный пресс-релиз про x8004 и МЧС.
                    +1
                    Очень симпатично. Отдельный респект за «sh — может все». =)) Я считаю, надо уже сделать отдельный блог с таким названием =))
                      0
                      Есть же оболочки.
                      0
                      Реализовано на небольшом предприятии уже сегодня моим другом. Голос сносный, можно использовать)
                        0
                        Прекрасная статья, спасибо :)

                        Only users with full accounts can post comments. Log in, please.