Пришла с час назад идея облегчить жизнь нашему персоналу — по ночам уведомлять их о падении оборудования телефонным звонком. При чем так, чтобы не просто «у вас что-то сломалось», а с указанием точного адреса.
Модуль мониторинга — где-то у админов, по событию они могут сгенерировать строку с адресом и номером телефона ответственного, так что задача сводится к тому, чтобы:
- Получить параметры
- Сформировать коллбек
- После поднятия трубки — продиктовать полученный адрес.
Нам потребуются:
- Сервер с астериском
- 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 минут механизма, получилось довольно неплохо.