Regular readers might remember my previous T-mobile Sidekick + Asterisk hacks. Not content with the performance of the Toll Averter, Wife Alerter, which uses a clunky synthesized voice to pronounce the text you ask it to send (but has no preview, so it’s not always clear whether the recipient will make sense of what was said), I set out recently to re-invent the project, this time as a direct-audio-delivery hack. Why would you want to record audio and deliver it rather than make a call directly? Easy, Sidekick’s have free e-mail sending, but voice minutes cost. Yes, I’m cheap. :)
I’ve been thinking about building a voice message with reply feature for a while. Sadly, this is about the clunkiest interface around, unlike the one Ping suggests.
Several things needed to come together to make this work. The Sidekick has no native voice recorder, but they recently added a tool called AudioLab to their catalog of tools (it costs $5). This tool lets you record audio, though it is limited to something like 10s at a time, and, unfortunately, suffers from a large-ish delay from hitting record to actually recording. But, it serves the important purpose, which is letting you record audio on the Sidekick, and ship it off somewhere via e-mail.
Now, to put it all together, I needed a way to receive mail, extract the wav file, ship the wav file to someplace that it could be reached by my Asterisk install, then initiate an outgoing call. I’ll go through each step in the extended.
Technorati Tags: voip, voiptricks
Composing the message
To send a message, you merely go into AudioLab and record whatever audio you want to send. It has a limit of about 10s of audio, and a ~3s recording delay. Nonetheless, its possible to send reasonable messages in this space, if you think ahead about what you’re going to say. Since this is offline composing, you can get the message right, rather than rattle off whatever’s on the top of your head when you hear the voicemail tone.
Once happy with the message, I send it to my super-secret e-mail address associated with the rest. AudioLab has a “Email Clip…” option, which basically just attaches the .wav file you’ve recorded to an e-mail, and opens the Sidekick’s e-mail compose window. From there, I change the subject line to the phone number I want the message delivered to, address the message to the magic address (I keep it in my address book, so it doesn’t have to be guessable-easy, although it currently is pretty simple), and hit “Send”.
For all of this to work, of course, I have to have a server running somewhere that receives my e-mail, and another (possibly the same) which has Asterisk is on it. I’m too cheap to get a big colocated host, so these are different machines, so some of the extra junk that follows is the process of automatically bridging the gap between two machines.
To receive the message, I use most of the same tricks as in the last sidekick voicemail hack. Namely, I have the magic e-mail address tagged in a procmail script, which activates a shell script. The shell script looks like this:
if ! TEMPDIR="`mktemp /tmp/sendwav.XXXXXX`"; then
echo "$0 is unable to create the temporary file."
# not perfect, but, we'll live
mkdir -p $TEMPDIR/source
mkdir -p $TEMPDIR/tomail
munpack -C $TEMPDIR/source
#convert to GSM
sox $TEMPDIR/source/*.[Ww][Aa][Vv] $TEMPDIR/out.gsm
#echo $SUBJECT > $TEMPDIR/target
#strip any spaces, ('s, or -'s out of the subject line
DESTCHANNEL=`echo "$SUBJECT" | tr -d " ()-"`
cat <<EOF1 > $SCRIPT
cp $TEMPDIR/tmp.call /var/spool/asterisk/
chmod a+r /var/spool/asterisk/tmp.call
chown asterisk /var/spool/asterisk/tmp.call
chmod a+r $TEMPDIR/out.gsm
mv /var/spool/asterisk/tmp.call /var/spool/asterisk/outgoing
echo rm -fr $TEMPDIR | at now + 10min
cat <<EOF2 > $TEMPDIR/tmp.call
Channel: [email protected]
shar $SCRIPT $TEMPDIR/tmp.call $TEMPDIR/out.gsm > $TEMPDIR/toxfer.shar
cat $TEMPDIR/toxfer.shar | ssh -C -i remote-ssh-identity [email protected] "cat - | sh - ; sh $SCRIPT"
rm -fr $TEMPDIR
This script is kind of tricky. First, the general flow:
1. Unpack the attachments of the received message.
2. Use the handy audio swiss-army-knife “sox” to convert any .wav attachment into a GSM file in a known location.
3. Extract the target phone number from the subject line of the message
4. Create a script file which will be run on the remote side. This script file will set up the outgoing .call file which asterisk will respond to. More on this below
5. Package up the script, pre-made .call file, and the .gsm file into a shar (shell archive, a funky old Unix trick).
6. Transmit the shell archive over a single ssh connection to the remote machine. During the same ssh session, unpack the share, and execute the included script. Head spinning yet? This overloaded trick lets you transmit a set of files and execute over a single SSH attempt… much tidier than normal, and it reduces the likelihood of tripping abuse-detecting code on the remote host.
The meat is above. The Asterisk part is what goes into the .call file. See here for a tidy description of the settings in this file. Basically, it specifies the target address (Channel:), and application to connect it to (a macro I’ll get to in a sec), and the sending caller ID, and the necessary arguments to that Macro to let it find the audio file converted from the original e-mail.
The macro is just responsible for the user interaction. I currently use the following, though I’d like to improve it somewhat to detect errors and possibly add a message back to the original sender to notify of successful delivery.
(put this in your extensions.conf or wherever you keep your macros)
exten => s,1,DigitTimeout,5 ; Set Digit Timeout to 5 seconds
exten => s,n,ResponseTimeout,10 ; Set Response Timeout to 10 seconds
exten => s,n,Answer
exten => s,n,Wait(1)
exten => s,n,Festival(eh recorded message from Bryan)
exten => s,n(play),Background() ; "play outbound msg"
exten => s,n,Festival(To repeat the message press 1 to leave a reply press 2.)
exten => s,n,Read(CHOICE,,1)
exten => s,n,Goto(,1)
exten => 1,1,Goto(s,play)
exten => 2,1,VoiceMail(101|s)
exten => t,n,Playback(vm-goodbye)
exten => t,n,Hangup
Note that VoiceMail 101 is the mailbox I’ve got hooked up to my voicemail delivery hack, so, I will immediately receive any replies that a recipient of one of these messages leaves.
If anyone else ends up adopting this code, please let me know, or feel free to ask questions. I’ve assumed a lot of unix experience in getting this going, but I’d be happy to help fill in the blanks for anyone who wants to give this a try but can’t quite follow at the level I’ve described it here.