Автоинформатор с произвольным текстом

Пришла с час назад идея облегчить жизнь нашему персоналу — по ночам уведомлять их о падении оборудования телефонным звонком. При чем так, чтобы не просто «у вас что-то сломалось», а с указанием точного адреса.

Модуль мониторинга — где-то у админов, по событию они могут сгенерировать строку с адресом и номером телефона ответственного, так что задача сводится к тому, чтобы:

  • Получить параметры
  • Сформировать коллбек
  • После поднятия трубки — продиктовать полученный адрес.

Нам потребуются:

  • Сервер с астериском
  • ffmpeg. Можно в дефолтной конфигурации
  • apache (у меня с mod_rewrite чтобы ограничить доступ к функционалу только конкретным инстансам)
  • 15 минут времени

Итак, приступим.

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

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

Код скрипта »

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 = '/asterisk/asterisk-callcentre/var/lib/asterisk/festivalcache/';
                        $filename = $prefix.$md5;
                        
                        if (!file_exists($filename.'.alaw')) {
				$wget = 'wget -q -U Mozilla -O '.$filename.'.mp3 "http://translate.google.com/translate_tts?ie=UTF-8&total=1&idx=0&textlen=256&client=tw-ob&q='.$text.'&tl='.$lang.'"';
                                $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);
?>

Правила для Астериска — также не представляют из себя ничего военного

Диалплан »

[incoming-ip.from-system-pinger]

;сюда попадаем на коллбеке. Нужно для занесения данных в CDR, или выполнения каких-либо доп. функций перед набором.
exten => _0[569]XXXXXXXX,1,Dial(SIP/38${DstCode}@outgoingtrunk)

;сюда попадаем после соединения с вызываемым
;пробелы перед тестом нужны для организации паузы перед произнесением
exten => s,1,AGI(/asterisk/agi/say.php,"  ${Message}",ru)
exten => s,2,HangUp

Для получения параметров от инициатора вызова в простейшей форме используется php-скрипт, принимающий параметры через $_GET. В дальнейшем возможно перепишем под $_POST.

Страница получения параметров »

<?php
$destination=$_GET["destination"];
$message=$_GET["message"];

if (substr($destination,0,3) == "+38")
{
$destination= substr($destination,3);
}

if (substr($destination,0,2) == "38")
{
$destination= substr($destination,2);
}


$callfile="/asterisk/asterisk-callcentre/var/spool/asterisk/tmp/call-pinger-".$destination.".call";
$cf =fopen($callfile,"w+");
fputs($cf,"Set: __DstCode=".$destination."n");
fputs($cf,"Set: __Message=".$message."n");
fputs($cf,"Channel: Local/1@incoming-ip.from-system-pingern");
fputs($cf,"Callerid: 38057XXXXXXXn");
fputs($cf,"Extension: sn");
fputs($cf,"Context: incoming-ip.from-system-pingern");
fputs($cf,"Priority: 1n");
fputs($cf,"MaxRetries: 5n");
fclose($cf);
copy($callfile,"/asterisk/asterisk-callcentre/var/spool/asterisk/outgoing/callback-pinger-".$destination.".call");
echo "dest=$destinationn";
echo "OKn";

?>

Что получаем в итоге

  • Внешний софт для инициирования уведомления посылает CURL формата /pingersay.php?destination=380комузвонить&message=»что говорить»
  • Страница формирует call-файл для коллбека, передавая локальные переменные для контекста. Переменные, описанные в call-файле, доступны для чтения в текущем контексте на всех этапах звонка.
  • Коллбек инициируется через localchannel, с передачей управления в контекст incoming-ip.from-system-pinger, где можно дополнительно играться с параметрами вызова первого плеча при необходимости
  • после соединения — управление передается в тот же контекст на экстеншен s, где вызывается созданный нами скрипт-говорилка, принимающий параметром текст.
  • PROFIT

Недостатки:

  • Гуглоробот не всегда корректно проставляет ударения в тексте
  • Гуглоробот гнусавит (да, гнусавит женским голосом)
  • Гуглоробот говорит довольно тихо. опция -vol в строке транскодинга почему-то не помогла увеличить громкость.

Требует доработки:

  • Громкость. Нужно пересобрать FFMpeg.
  • Передача параметров через форму.

Однако, как для реализованного за 15 минут механизма, получилось довольно неплохо.

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

Войти с помощью: