Automated recording with Asterisk

So I decided to write a recipe for recording conference calls with Asterisk. Let’s say you have a dialin bridge number and a bridge passcode and you want your server to connect at certain times, announce that you are going to record (and periodically remind that you are doing so), and then do so. Optionally, you might ask the moderator to confirm this by pressing a key. You might spend many hours figuring this out, which is why I’m going to show you how.

First, you need some canned audio files. I use the following in my example (which I record using a studio microphone and then convert into sln files with the sox command: sox jcm-beep.wav -t raw -r 8000 -s -c 1 jcm-beep.sln):

  • jcm-beep – a tone indicating recording is ongoing
  • jcm-record_question – ask the moderator if they want to record
  • jcm-record_confirm – confirm that you will begin recording
  • jcm-record_cancel – announce that you have not made a recording
  • jcm-record_reminder – reminder that you are recording
  • jcm-record_limit – announce that recording time has been exceeded
  • jcm-record_timeout – announce that the limit for a response was exceeded

With those recordings in place (/usr/share/asterisk/sounds for example), add the following subroutine “context” to your /etc/asterisk/extensions.conf:

[conf-record]

exten => h,1,Set(GOSUB_RESULT=ABORT)
exten => h,2,Return()

exten => s,1,Answer()
exten => s,2,Wait(2)
exten => s,3,Set(STARTSTAMP=${EPOCH})
exten => s,4,Set(TIMEOUTSECS=30)                                                ; 30 second timeout
exten => s,5,SendDTMF(00${CONFCALLPWD},200)
exten => s,6,Wait(15)
exten => s,7,Set(WAITSTART=${EPOCH})
exten => s,8,GotoIf($[${ASKTORECORD} == 1]?100)
exten => s,9,Goto(9,1)

exten => s,100,Set(WAITTIME=$[${EPOCH}-${WAITSTART}])
exten => s,101,BackGround(jcm-record_question)
exten => s,102,WaitExten(5)
exten => s,103,GotoIf($[${WAITTIME} <= ${TIMEOUTSECS}]?100)
exten => s,104,PlayBack(jcm-record_timeout)
exten => s,105,Set(GOSUB_RESULT=ABORT)
exten => s,106,Return()

exten => 6,1,Answer()
exten => 6,2,PlayBack(nothing-recorded)
exten => 6,3,PlayBack(goodbye)
exten => 6,4,Set(GOSUB_RESULT=ABORT)
exten => 6,5,Return()

exten => 9,1,Answer()
exten => 9,2,Set(MAXRECORDSECS=4000)                                            ; just over 1 hour
exten => 9,3,GotoIf($["${CONFCALLNAME}" != ""]?100)
exten => 9,4,Set(CONFCALLNAME=conf-call-${STRFTIME(,,%Y%m%d-%H%M%S)})
exten => 9,5,Goto(100)

exten => 9,100,Set(CALLREMINDBEEPINT=180) ; time in secs between beeps
; every 3 minutes
exten => 9,101,Set(CALLREMINDMSGMULT=5) ; number of beeps before message        ; every 15 minutes
exten => 9,102,Set(CALLREMINDBEEPCNT=0) ; current number of beeps
exten => 9,103,Set(CALLFILENAME=${CONFCALLNAME}-${STRFTIME(,,%Y%m%d-%H%M%S)})
exten => 9,104,Monitor(wav,${CALLFILENAME},m)
exten => 9,105,Set(RECORDSTART=${EPOCH})
exten => 9,106,PlayBack(jcm-beep)
exten => 9,107,PlayBack(jcm-record_reminder)
exten => 9,108,Goto(200)

exten => 9,200,Set(RECORDTIME=$[${EPOCH}-${RECORDSTART}])
exten => 9,201,Wait(${CALLREMINDBEEPINT})
exten => 9,202,PlayBack(jcm-beep)
exten => 9,203,Set(CALLREMINDBEEPCNT=$[${CALLREMINDBEEPCNT}+1])
exten => 9,204,GotoIf($[${CALLREMINDBEEPCNT} < ${CALLREMINDMSGMULT}]?210)
exten => 9,205,PlayBack(jcm-record_reminder)
exten => 9,206,Set(CALLREMINDBEEPCNT=0)
exten => 9,207,Goto(210)
exten => 9,210,GotoIf($[${RECORDTIME} <= ${MAXRECORDSECS}]?200)
exten => 9,211,PlayBack(jcm-record_limit)
exten => 9,212,Set(GOSUB_RESULT=ABORT)
exten => 9,213,Return()

Notice that there are still a few hard-coded variables in there, and that the bridge password is always prefixed with a “00″ since these first digits are generally lost in my case). There are two good ways to use this. The first is to add a test extension on your local server, which you can do using the Dial command with an option including U(conf-record). Since there’s a bug in the version of Asterisk I am running (now fixed upstream), I also append S(1) to force the call to hangup on successful connection. A more useful way to use this is with a call file. Create something like the following call_fedora_talk.call file (I prefix variables with double underscores to ensure they are always inherited with call properties):

Channel:	SIP_OR_IAX_TRUNK_HERE/19783038021
Callerid:	YOUR_CALLER_ID
WaitTime:	60
Context:	conf-record
Extension:	s
Priority:	1
SetVar:		__CONFCALLNAME=fedora-talk-testcall
SetVar:		__ASKTORECORD=1
SetVar:		__CONFCALLPWD=2014

This is configured to connect to Fedora Talk conference room 2014 (general purpose room), announce itself, ask if it is ok to record, and then begin the recording (some conferenece systems don’t pass through DTMF, so you might need to explicitly disable ASKTORECORD in those cases – especially if you have permission anyway). If you copy this file into your /var/spool/asterisk/outgoing directory with correct ownership (for example, using vixie cron) then Asterisk will detect it and begin the recording. Those on the call will hear (for example): “beep…just a reminder that this call is being recorded”. Then every 3 minutes they will hear a (gentle!) sound, and every 15 they will hear an audible reminder that the call is being recorded like at the beginning. After recording, the call will be placed in the usual monitor directory. Have fun!

Jon.

Leave a Reply