CentOS & Asterisk. Часть 4. Запись разговоров.


28.11.2018

Всем привет. В этой статье поговорим про запись телефонных разговоров нашего телефонного сервера. Обычно в статьях в сети, в качестве хранилища записей звонков, используют каталог внутри самой виртуальной машины, и на мой взгляд это очень неудобно – как в плане вместительности, так и в плане дальнейшей доступности к этим записям. Я придерживаюсь того что нужно складывать записи на сетевой путь, допустим на NAS ну или расшаренную в Windows директорию. В среде Linux есть совершенно волшебная возможность примонтировать сетевой путь в качестве каталога в собственной файловой системе. Например, будучи в CentOS – мы заходим в каталог «/mnt/callrecords» и видим там содержимое каталога на удалённой машине. Давайте для начала подготовим папку куда будут складываться записи:

И так мы имеем расшаренный в сети ресурс с такими параметрами:

IP: 192.168.3.22
Каталог: records
User: mradmin
Password: 123

Теперь запускаем PuTTY – подключаемся к нашему серверу под root пользователем и пишем:

yum -y install samba-client cifs-utils

Теперь создаём каталог куда будет монтироваться сетевой путь:

mkdir /mnt/callrecords

Меняем владельца каталога:

chown -R asteriskpbx:asteriskpbx /mnt/callrecords

Далее делаем каталог доступным для всех:

chmod -R 777 /mnt/callrecords

Монтируем:

mount -t cifs //192.168.3.22/records /mnt/callrecords -o username=mradmin,password=123

поверим содержимое:

ls /mnt/callrecords

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

nano /root/callrecuser

И вписываем свои данные:

username=mradmin
password=123

Сохраняем и закрываем. Далее жёстко ограничим права на этот файл:

chmod 400 /root/callrecuser

Теперь редактируем файл, отвечающий за автозагрузку «/etc/fstab»:

nano /etc/fstab

Добавляем в конце строчку всё одной строкой:

;Вся команда одной строкой
//192.168.3.22/records /mnt/callrecords cifs uid=asteriskpbx,gid=asteriskpbx,rw,credentials=/root/callrecuser,iocharset=utf8,sec=ntlm 0 0
;;;;;;;;;;;;;;;;;

Ого-го мы научились в Linux монтировать в каталог сетевой шаринг! Аккуратней с нами теперь! Аккуратней! Отлично! Едем дальше - теперь работаем с конфигами:

Редактируем в конце «extensions.conf» командой «nano /etc/asterisk/extensions.conf»:

;;;;;;;;;;;;;;;;;;;
[localcalls]
exten => _X.,1,Set(fname=${STRFTIME(${EPOCH},,%Y%m%d%H%M)}-${CALLERID(number)}-${EXTEN})
exten => _X.,2,MixMonitor(/mnt/callrecords/${fname}.wav)
exten => _XXXXXXXXXXX,3,Dial(SIP/zadarma/${EXTEN})
exten => _XXX,3,Dial(SIP/${EXTEN},30,t&m)
exten => 104,3,Goto(menu,start,1)
[menu]
exten => start,1,Set(fname=${STRFTIME(${EPOCH},,%Y%m%d%H%M)}-${CALLERID(number)}-${EXTEN})
exten => start,2,MixMonitor(/mnt/callrecords/${fname}.wav)
exten => start,3,Answer()
same => n,Background(/var/lib/asterisk/moh/vmenu/vmenu)
same => n,WaitExten(5)
exten => start,n,Dial(SIP/105,30)
exten => 1,1,Dial(SIP/101,30) ;если звонящий нажал цифру 1, то звоним 101
same => n,Goto(menu,start,1)
exten => 2,1,Dial(SIP/102,30) ;если звонящий нажал цифру 2, то звоним 102
same => n,Goto(menu,start,1)
exten => 3,1,Dial(SIP/103,30) ;если звонящий нажал цифру 3, то звоним 103
same => n,Goto(menu,start,1)
[vneshka]
exten => _X.,1,Answer()
same => n,Goto(menu,start,1)
;;;;;;;;;;;;;;;;;;;

Сохраняем и выходим.

Кстати – номер 104 мы создали исключительно для эмуляции звонков из-вне – то есть строчка «exten => 104,3,Goto(menu,start,1)» и не нужна вовсе. Ниже модифицированный план набора:

;;;;;;;;;;;;;;;;;;;
[localcalls]
exten => _X.,1,Set(fname=${STRFTIME(${EPOCH},,%Y%m%d%H%M)}-${CALLERID(number)}-${EXTEN})
exten => _X.,2,MixMonitor(/mnt/callrecords/${fname}.wav)
exten => _XXXXXXXXXXX,3,Dial(SIP/zadarma/${EXTEN})
exten => _XXX,3,Dial(SIP/${EXTEN},30,t&m)
[menu]
exten => start,1,Set(fname=${STRFTIME(${EPOCH},,%Y%m%d%H%M)}-${CALLERID(number)}-${EXTEN})
same => n,MixMonitor(/mnt/callrecords/${fname}.wav)
same => n,Answer()
same => n,Background(/var/lib/asterisk/moh/vmenu/vmenu)
same => n,WaitExten(5)
exten => start,n,Dial(SIP/105,30)
exten => 1,1,Dial(SIP/101,30) ;если звонящий нажал цифру 1, то звоним 101
same => n,Goto(menu,start,1)
exten => 2,1,Dial(SIP/102,30) ;если звонящий нажал цифру 2, то звоним 102
same => n,Goto(menu,start,1)
exten => 3,1,Dial(SIP/103,30) ;если звонящий нажал цифру 3, то звоним 103
same => n,Goto(menu,start,1)
[vneshka]
exten => _X.,1,Answer()
same => n,Goto(menu,start,1)
;;;;;;;;;;;;;;;;;;;

На всякий случай надо заметить, что данный диал план подразумевает что у организации всего один внешний номер и когда нам звонят извне то попадают на автоответчик, который голосом говорит какую цифру набрать для связи с тем или иным специалистом. А с него, если человек не выберет ни одной цифры, звонок уйдёт на секретаря (105), и при этом абсолютно все разговоры записываются на сетевой путь.

Давайте добавим возможность звонящим нам людям оставлять голосовое сообщение. Для это мы запишем дополнительное голосовое сообщение и назовём его «busy». Положим его вот сюда - «/var/lib/asterisk/moh/vmenu/busy.wav». В сообщении будет сказано «К сожалению в данный момент все специалисты заняты – оставьте сообщение после звукового сигнала». Ну а теперь переделаем наш диал план:

;;;;;;;;;;;;;;;;;;;
[localcalls]
exten => _X.,1,Set(fname=${STRFTIME(${EPOCH},,%Y%m%d%H%M)}-${CALLERID(number)}-${EXTEN})
exten => _X.,2,MixMonitor(/mnt/callrecords/${fname}.wav)
exten => _XXXXXXXXXXX,3,Dial(SIP/zadarma/${EXTEN})
exten => _XXX,3,Dial(SIP/${EXTEN},30,t&m)
[menu]
exten => start,1,Set(fname=${STRFTIME(${EPOCH},,%Y%m%d%H%M)}-${CALLERID(number)}-${EXTEN})
same => n,MixMonitor(/mnt/callrecords/${fname}.wav)
same => n,Answer()
same => n,Background(/var/lib/asterisk/moh/vmenu/vmenu)
same => n,WaitExten(5)
exten => start,n,Dial(SIP/105,30)
same => n,Playback(/var/lib/asterisk/moh/vmenu/busy)
same => n,Wait(1)
same => n,Goto(autoanswer,anstart,1)
exten => 1,1,Dial(SIP/101,30) ;если звонящий нажал цифру 1, то звоним 101
same => n,Goto(menu,start,1)
exten => 2,1,Dial(SIP/102,30) ;если звонящий нажал цифру 2, то звоним 102
same => n,Goto(menu,start,1)
exten => 3,1,Dial(SIP/103,30) ;если звонящий нажал цифру 3, то звоним 103
same => n,Goto(menu,start,1)
[autoanswer]
exten => anstart,1,Wait(1)
same => n,Set(answ=${STRFTIME(${EPOCH},,%Y%m%d%H%M)}-${CALLERID(number)}-${EXTEN})
same => n,Record(/mnt/callrecords/${answ}.wav,,,k)
same => n,Hangup
[vneshka]
exten => _X.,1,Answer()
same => n,Goto(menu,start,1)
;;;;;;;;;;;;;;;;;;;


А теперь давайте разберём каждую строчку:

Контекст [localcalls]:


exten => _X.,1,Set(fname=${STRFTIME(${EPOCH},,%Y%m%d%H%M)}-${CALLERID(number)}-${EXTEN})

Первым делом в контексте срабатывает «exten», который при звонке абсолютно на любой номер «_X.» берёт командой «Set» переменную «fname» и запоминает в неё год, месяц, день, час, минуту, а затем через тире – кто звонит и через тире – куда звонит. Вот так например - 201811290821-100-101.wav.


exten => _X.,2,MixMonitor(/mnt/callrecords/${fname}.wav)

Этой строкой – правило на тот же шаблон «_X.», но уже с очерёдностью 2 – запускается запись wav файла, используя переменную в качестве названия.


exten => _XXXXXXXXXXX,3,Dial(SIP/zadarma/${EXTEN})

Это знакомое нам правило звонков на внешние 11ти значные номера, используя абонента «zadarma» - а это напомню наше транк соединение через провайдера для звонков на внешку. У правила стоит очередность 3 – потому что получается что шаблон «_X.» в общем то аналогичен шаблону «_XXXXXXXXXXX» а он забрал первые 2 очерёдности и вот поэтому очерёдность 3.


exten => _XXX,3,Dial(SIP/${EXTEN},30,t&m)

Это тоже знакомое нам правило звонков на местные 3х значные номера, используя очередность 3 – потому что получается, что шаблон «_X.» тоже аналогичен шаблону «_XXX» и он тоже забрал первые 2 очерёдности, и вот поэтому очерёдность 3. Также параметр «30» говорит нам о том что вызов длится 30 секунд и если никто не взял трубку то звонок переходит на следующее правило. «t&m» - «t» - означает что есть возможность сделать трансфер а «m» - то что используется музыка а не гудки в трубке. Кстати музыку можно поставить свою если в конфиге «/etc/asterisk/musiconhold.conf» - найти раздел «[default]» и поменять в строке «directory=moh» на свой путь, но путь должен быть именно к каталогу.


Контекст [menu]:


exten => start,1,Set(fname=${STRFTIME(${EPOCH},,%Y%m%d%H%M)}-${CALLERID(number)}-${EXTEN})

start – это своего рода замена шаблона – то есть как бы отправная точка контекста. И далее тоже самое – запоминаем в переменную нужные данные для формирования названия файла записи.


same => n,MixMonitor(/mnt/callrecords/${fname}.wav)

Конструкция «same => n,» - по сути замена «exten => start,2,» то есть мы её используем если нам надо просто описать правило действия звонка, которое действует после выполнения предыдущей строки. То есть выставленная очерёдность «n» говорит плану набора что это не конкретная очередь, а просто делай это дальше.


same => n,Answer()

Далее - команда поднять трубку


same => n,Background(/var/lib/asterisk/moh/vmenu/vmenu)

Далее проигрываем запись приветствия


same => n,WaitExten(5)

Далее ждём 5 секунд ПОСЛЕ окончания проигрывания приветствия


exten => start,n,Dial(SIP/105,30)

Если человек не выбрал ни одной цифры и прошло 5 секунд – звонок уходит на приёмную (105)


same => n,Playback(/var/lib/asterisk/moh/vmenu/busy)

И если за 30 секунд приёмная не взяла трубку то проигрывается запись что все заняты – оставьте сообщение после сигнала


same => n,Wait(1)

Ждём секунду


same => n,Goto(autoanswer,anstart,1)

и уводим звонок на контекст «[autoanswer]»


exten => 1,1,Dial(SIP/101,30) ;если звонящий нажал цифру 1, то звоним 101

Ну а если же человек выбрал цифру 1 то переводим звонок на номер 101


same => n,Goto(menu,start,1)

Если 101 не взял трубку в течение 30 секунд, то возвращаем звонок на меню


exten => 2,1,Dial(SIP/102,30) ;если звонящий нажал цифру 2, то звоним 102

Ну а если же человек выбрал цифру 2 то переводим звонок на номер 102


same => n,Goto(menu,start,1)

Если 102 не взял трубку в течение 30 секунд, то возвращаем звонок на меню


exten => 3,1,Dial(SIP/103,30) ;если звонящий нажал цифру 3, то звоним 103

Ну а если же человек выбрал цифру 3 то переводим звонок на номер 103


same => n,Goto(menu,start,1)

Если 103 не взял трубку в течение 30 секунд, то возвращаем звонок на меню


Контекст [autoanswer]:


exten => anstart,1,Wait(1)

Запускаем контекст с отправной точкой «anstart» и командой ожидания в 1 секунду


same => n,Set(answ=${STRFTIME(${EPOCH},,%Y%m%d%H%M)}-${CALLERID(number)}-${EXTEN})

Запоминаем в переменную «answ» нужные данные для названия файла


same => n,Record(/mnt/callrecords/${answ}.wav,,,k)

Запускаем запись используя переменную «answ» в качестве названия файла. «.wav» говорит что файл будет в формате wav. Далее 3 запятых без параметров – почему? Разберём – после первой запятой ставится количество секунд тишины, после которой система сама закончит запись, не дожидаясь, когда звонящий положит трубку. После второй запятой количество секунд лимитирования длинны самой записи – что весьма непрактично. После третьей запятой стоит параметр «k» - просто потому что если его не поставить, то запись не сохраняется.


same => n,Hangup

Кладём трубку после окончания записи


Контекст [vneshka]:

Напоминаю что этот контекст нужен для того чтобы нам звонили извне


exten => _X.,1,Answer()

Контекст стартует правилом говорящим о том что если звонок идёт на любой номер то подними трубку


same => n,Goto(menu,start,1)

И переводи звонок на меню.



Все ссылки для данного проекта:

Пакет русских сервисных сообщений (asterisk-core-sounds-ru-alaw-current) asterisk-core-sounds-ru-alaw-current drive.google.com
Asterisk CDR Viewer https://github.com/g613/asterisk-cdr-viewer drive.google.com
Ease Audio Converter http://audiotool.net/EaseAudioConverter/index.htm
Adobe Audition https://www.adobe.com/ru/products/audition.html
WinSCP https://winscp.net/eng/download.php
CentOS-7-x86_64-Minimal-1804.iso https://www.centos.org/download drive.google.com
Исходник asterisk-15.6.2 https://downloads.asterisk.org/pub/telephony/asterisk/asterisk-15.6.2.tar.gz drive.google.com
Исходник dahdi-linux: https://downloads.asterisk.org/pub/telephony/dahdi-linux/dahdi-linux-current.tar.gz drive.google.com
Исходник libpri-current: https://downloads.asterisk.org/pub/telephony/libpri/libpri-current.tar.gz drive.google.com
X-lite: https://www.counterpath.com/x-lite-download/ drive.google.com
Официальная wiki https://wiki.asterisk.org/wiki/display/AST/Home


Навигация: