IP-телефония на базе Asterisk
Введите свой номер телефона
и мы перезвоним вам
Решаем Ваши бизнес-задачи с помощью IT-технологий. Знаем, как сделать лучше, быстрее и дешевле. Наш опыт – на службе Вашего бизнеса.
Не все герои носят плащи. Сотни техических статей, написанных инженерами нашей компании. Делимся опытом и своими знаниями со всем сообществом.
Сотни функций и возможностей Asterisk помогут вывести коммуникации в Вашей компании на принципиально новый уровень. Технические ограничения – фантазия Заказчика.
Вы платите за систему, которая будет полностью соответствовать Вашим ожиданиям, требованиям и будет драйвером роста Вашего бизнеса
Идти в ногу со временем или оставаться на старых технологиях? Такой вопрос не стоит перед нашими клиентами. Решаем самые смелые задачи для Колл-Центров. Строим с нуля или работаем с существующими.
Поместите свой бизнес в эпицентр продаж. Интеграция IP-телефонии и CRM даст новый и мощный импульс Вашему Отделу Продаж и выведет компанию на три шага впереди конкурентов.
Подбираем для клиентов такие тарифы, которые ему редко получится найти на рынке самостоятельно. Работаем с 100+ операторов связи в интересах клиента.
Разработки, созданные нашей командой под запросы клиентов. Не отказывайтесь от инноваций. Мы поможем идти с ногу со временем.
Умные всю жизнь учатся, а остальные всегда все и так знают. Мы проводим обучение более 8 лет и выпустили более 1000 специалистов по Asterisk и Mikrotik. Проводим ежегодную конференцию Asterisk.
Купить наш опыт дешевле, чем набивать свои шишки. Мы реализовали более 800 проектов и накопили экспертизу для того, чтобы идеально выполнить Ваш проект.
Правильный выбор оборудования позволяет сэкономить от 20 до 50% бюджета телефонии. Мы предельно внимательно подойдем к выбору «железа» в Ваш проект.
Наши цены доступны не только для Москвы, но и для регионов. А вложения в нашу экспертизу обычно окупаются за несколько месяцев.
Работаем с 2011 года. Собрали отличную команду реальных фанатов своего дела. Подходим к работе с душой и ответственностью.
Доклад систематизирует практику построения диалпланов в Asterisk с акцентом на паттерны набора, специальные экстеншены, поведение приложений Dial, Playback/Background, работу с переменными и функциями, а также на типовые приёмы IVR и запись разговоров (включая постобработку).
Примеры:
Приоритет масок: чем конкретнее экстеншен (например, точное число «1001» против шаблона _1XXX), тем выше его приоритет при выборе.
Типичный фрагмент:
exten => 1001,1,NoOp(Before Dial)
same => n,Dial(PJSIP/1001)
same => n,NoOp(After Dial - executed only if not answered)
exten => h,1,NoOp(Hangup hook - always runs after call ends)
По умолчанию (без опции g у Dial) дальнейшие приоритеты после Dial() выполняются, если вызов не был отвечен (состояния BUSY/NOANSWER/CONGESTION/…). Если вызов был отвечен и затем завершён, выполняется exten => h,1,…. Именно поэтому постобработку (например, архивирование записи) рационально помещать в h.
Приложение NoOp() (в расшифровке No Operation) — удобный способ вывести в консоль/лог диагностическое сообщение:
same => n,NoOp(UNIQUEID=${UNIQUEID} EXTEN=${EXTEN} DIALSTATUS=${DIALSTATUS})
Используется для трассировки диалплана и значений переменных.
Уровни и доступ
Часто применяемые встроенные переменные:
CALLERID() — это функция, как и STRFTIME(). Чтение/запись выполняется через синтаксис функций.
STRFTIME() для меток времени и каталогов
Примечание: при записи в подкаталоги следует обеспечить их существование заранее (например, через System(/bin/mkdir -p …) в момент старта).
Метки и n
При использовании same => n(…) допускается именовать приоритет и затем переходить к нему:
exten => s,1,NoOp(Start)
same => n(start),Background(main-menu)
same => n,WaitExten(5,m) ; ожидание DTMF + музыка ожидания по опции 'm'
same => n,Goto(s,start) ; возврат к началу меню
Важно указывать правильный экстеншен при переходе к метке: Goto(s,start) перейдёт к метке start в exten => s.
Условия
Условный переход
same => n,GotoIf($[ "${CALLERID(num)}" = "303" ]?prio3:next)
В зависимости от времени (рабочее/нерабочее)
same => n,GotoIfTime(09:00-18:00,mon-fri,*,*?open:closed)
Рекомендуется применять Gosub() для повторно используемых блоков. В отличие от устаревшего Macro, возврат из подпрограммы осуществляется явным Return().
Основной поток
exten => _X.,1,Gosub(sub-record,${EXTEN},1)
same => n,Dial(${PJSIP_DIAL_CONTACTS(${EXTEN})})
Подпрограмма записи
[sub-record]
exten => _X.,1,NoOp(Recording bootstrap)
same => n,Set(DATE=${STRFTIME(${EPOCH},,%Y/%m/%d)})
same => n,Set(REC_BASE=${DATE}/${CALLERID(num)}_${EXTEN}_${UNIQUEID})
same => n,Return()
Background vs Playback
В IVR чаще применяется Background.
[ivr-main]
exten => s,1,Background(company/welcome)
same => n,WaitExten(5,m) ; 5 сек, 'm' — музыка ожидания
exten => 1,1,Goto(ivr-sales,s,1)
exten => 2,1,Goto(ivr-support,s,1)
exten => t,1,Playback(vm-goodbye) ; timeout
same => n,Goto(ivr-main,s,1)
exten => i,1,Playback(pbx-invalid) ; invalid
same => n,Goto(ivr-main,s,1)
Альтернатива — Read(var,file,timeout,maxdigits,…), когда требуется собрать конкретное количество цифр и сохранить их в переменную.
Функция DEVICE_STATE() позволяет проверять состояние устройства/эндпоинта и ветвить логику:
Пример (упрощённо)
exten => 1001,1,Set(STATE=${DEVICE_STATE(PJSIP/1001)})
same => n,GotoIf($["${STATE}"="NOT_INUSE"]?ring:busy)
same => n(busy),Playback(line-busy)
same => n,Hangup()
same => n(ring),Dial(${PJSIP_DIAL_CONTACTS(1001)})
Для мульти-регистраций корректнее использовать функцию PJSIP_DIAL_CONTACTS(endpoint), которая возвращает готовую dial-строку на все контактные адреса AOR:
same => n,Dial(${PJSIP_DIAL_CONTACTS(${EXTEN})})
Это гарантирует прозвон всех активных контактов эндпоинта, вместо попыток дозвона только к последнему зарегистрированному.
Базовый запуск записи
На практике удобнее писать через MixMonitor() (смешивание каналов) и использовать экстеншен h для постобработки:
Подготовка имени
exten => _X.,1,Set(DATE=${STRFTIME(${EPOCH},,%Y/%m/%d)})
same => n,Set(REC_BASE=${DATE}/${CALLERID(num)}_${EXTEN}_${UNIQUEID})
Запуск записи (микшированный WAV)
same => n,MixMonitor(${REC_BASE}.wav,b) ; 'b' — писать только в бридже
same => n,Dial(${PJSIP_DIAL_CONTACTS(${EXTEN})})
Постобработка по завершению
exten => h,1,NoOp(Post-process ${REC_BASE})
; пример: конвертация в mp3
same => n,System(/usr/bin/ffmpeg -y -i /var/spool/asterisk/monitor/${REC_BASE}.wav \
-codec:a libmp3lame -qscale:a 4 \
/var/spool/asterisk/monitor/${REC_BASE}.mp3)
При необходимости получить раздельные направления «вход»/«выход» и затем собрать их в стерео:
Дополнительно попросить MixMonitor сохранить «rx/tx» дорожки: в современных версиях используются опции вида r(filename) и t(filename) в параметре options.
Пример (схематично):
same => n,MixMonitor(,r(${REC_BASE}-in.wav)t(${REC_BASE}-out.wav))
Аудиофайлы будут закрыты на момент остановки MixMonitor.
Сборка в стерео командой post-process на MixMonitor (3-й параметр):
same => n,MixMonitor(${REC_BASE}.wav,b,/usr/bin/sox -M \
/var/spool/asterisk/monitor/${REC_BASE}-in.wav \
/var/spool/asterisk/monitor/${REC_BASE}-out.wav \
/var/spool/asterisk/monitor/${REC_BASE}-stereo.wav)
Опция «команда» у MixMonitor выполняется после остановки записи, поэтому безопаснее, чем запуск внешних утилит через System() ещё до закрытия файлов.
CLI-справочник:
Для русских голосовых наборов звуков выбирать русские промты при сборке/установке (sounds с ru).
[ivr-main]
exten => s,1,NoOp(IVR start)
same => n(start),Background(custom/ivr-welcome) ; приветствие
same => n,WaitExten(5,m)
Разделы
exten => 1,1,Goto(ivr-sales,s,1)
exten => 2,1,Goto(ivr-support,s,1)
Прямой набор внутренних
exten => _1XXX,1,Goto(from-internal,${EXTEN},1)e
обработка ошибок
exten => i,1,Playback(pbx-invalid)
same => n,Goto(s,start)
exten => t,1,Playback(vm-goodbye)
same => n,Goto(s,start)
Билеты уже в продаже!
Я - Кондрашин Игорь, менеджер компании Voxlink. Хотите уточнить детали или готовы оставить заявку? Укажите номер телефона, я перезвоню в течение 3-х секунд.