Skip to content

Instantly share code, notes, and snippets.

@jtsage
Last active July 31, 2025 21:06
Show Gist options
  • Select an option

  • Save jtsage/f38151b43debb6bd90ebaa4f0ab2687f to your computer and use it in GitHub Desktop.

Select an option

Save jtsage/f38151b43debb6bd90ebaa4f0ab2687f to your computer and use it in GitHub Desktop.
Asterisk Voicemail --> MP3 w/ IBM bluemix trasnscription
#!/bin/bash
# Asterisk Voicemail -> MP3 And IBM Bluemix Transcription
# Set CONFIG_DEBUG to 1 (not zero) to disable file deletion on completion.
# Logs are written to mail.info (likely /var/log/mail.log)
# Bluemix response will be in /tmp/astVM.XXXXXXXX/audio.txt
CONFIG_DEBUG=0
CONFIG_API_PRIV_KEY="XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
CONFIG_API_INSTANCE="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
CONFIG_API_MODEL="en-US_Telephony"
CONFIG_API_HOST="us-east" # https://api.us-east.speech-to-text.watson.cloud.ibm.com
# Brief Version History
# 2010-11-22 - Creation by N. Bernaerts
# 2012-05-08 - MP3 Compression Fixes by Luca Mancino
# 2012-08-01 - PATH definition fix by Christopher Wolff
# 2015-07-16 - Native GSM WAV by Michael Munger
# 2015-08-17 - Work by Jason Klien
# 2017-09-17 - Work by lqaetz
# 2020-04-16 - API key work by JTSage
# 2025-07-30 - FreeBSD17 updates, bash conversion, and logging by jtsage
#
# Usage:
# 1.) copy this file to /usr/sbin/ and make it executable by asterisk (chmod 755)
# 2.) In the [general] section of /etc/asterisk/voicemail.conf set mailcmd=/usr/sbin/sendmail.asterisk
# - OR -
# 2.) Set the mail command in Settings->Voicemail Admin->Settings->Email Config (last item)
#
# Permissions - More: Make sure the asterisk user can execute (and that they exist - fwiw, a new
# install of FreePBX 17 circa July 2025, lame and sox existed):
# * dos2unix [# apt install dos2unix]
# * unix2dos
# * sox
# * lame
# * jq [# apt install jq]
#
# set PATH
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
# Generate the bluemix URL
API_URL="https://api.$CONFIG_API_HOST.speech-to-text.watson.cloud.ibm.com/instances/$CONFIG_API_INSTANCE/v1/recognize?model=$CONFIG_API_MODEL"
exec 1> >(exec logger -p mail.info -t $(basename $0)) 2>&1
# save the current directory
pushd . > /dev/null
# Create temporary working directory
TMPDIR=$(mktemp -d /tmp/astVM.XXXXXXXXXX)
cd "$TMPDIR"
# dump the stream to a temporary file
cat >> stream.org
# Extract MIME boundary
BOUNDARY=$(grep "boundary=" stream.org | cut -d'"' -f 2)
# cut the file into parts
# stream.part - header before the boundary
# stream.part1 - header after the boundary
# stream.part2 - body of the message
# stream.part3 - attachment in base64 (WAV file)
# stream.part4 - footer of the message
awk '/'$BOUNDARY'/{i++}{print > "stream.part"i}' stream.org
# if mail is having no audio attachment (plain text)
PLAINTEXT=$(cat stream.part1 | grep 'plain')
if [ "$PLAINTEXT" != "" ]
then
# prepare to send the original stream
echo "plain text e-mail found, bypassing"
cp stream.org stream.new
else
echo "processing voicemail message"
# cut the attachment into parts
# stream.part3.head - header of attachment
# stream.part3.wav.base64 - wav file of attachment (encoded base64)
sed '7,$d' stream.part3 > stream.part3.wav.head
sed '1,6d' stream.part3 > stream.part3.wav.base64
# convert the base64 file to a wav file
dos2unix -o stream.part3.wav.base64
base64 -di stream.part3.wav.base64 > stream.part3.wav
# Send WAV to Watson Speech to Text API.
CURL_OPTS=""
curl -s $CURL_OPTS -k -u "apikey:$CONFIG_API_PRIV_KEY" -X POST \
--show-error \
--limit-rate 40000 \
--header "Content-Type: audio/wav" \
--data-binary @stream.part3.wav \
"$API_URL" 1>audio.txt
# Extract transcript results from JSON response
TRANSCRIPT=`jq -er '.results[].alternatives[] | "[\(.confidence)] \(.transcript)"' audio.txt`
# convert wave file (GSM encoded or not) to PCM wav file
sox -V1 stream.part3.wav stream.part3-pcm.wav
# convert PCM wav file to mp3 file
# -b 24 is using CBR, giving better compatibility on smartphones (you can use -b 32 to increase quality)
# -V 2 is using VBR, a good compromise between quality and size for voice audio files
lame -S -m m -b 24 stream.part3-pcm.wav stream.part3.mp3
# convert back mp3 to base64 file
base64 stream.part3.mp3 > stream.part3.mp3.base64
# generate the new mp3 attachment header
# change Type: audio/x-wav or audio/x-WAV to Type: audio/mpeg
# change name="msg----.wav" or name="msg----.WAV" to name="msg----.mp3"
sed -E 's/x-[wW][aA][vV]/mpeg/g; s/\.[wW][aA][vV]/.mp3/g' stream.part3.wav.head > stream.part3.mp3.head
# generate first part of mail body, converting it to LF only
mv stream.part stream.new
cat stream.part1 >> stream.new
sed '$d' < stream.part2 >> stream.new
# transcription section
{
echo -e "\n--- Automated transcription result ---\n"
echo "$TRANSCRIPT"
tail -1 stream.part2
cat stream.part3.mp3.head
} >> stream.new
dos2unix -o stream.new
# append base64 mp3 to mail body, keeping CRLF
unix2dos -o stream.part3.mp3.base64
cat stream.part3.mp3.base64 >> stream.new
# append end of mail body, converting it to LF only
{
echo ""
echo ""
cat stream.part4
} > stream.tmp
dos2unix -o stream.tmp
cat stream.tmp >> stream.new
fi
# Send email
sendmail -t < stream.new
# Cleanup
popd > /dev/null
# remove all temporary files and temporary directory
# if things are not working, this is a great place to
# start. If, as in my experience, you can't find the
# temp folder than, check your spelling that FreePBX
# is trying to run the right script.
if [ "$CONFIG_DEBUG" -eq 0 ]; then
rm -Rf $TMPDIR
fi
@jtsage
Copy link
Author

jtsage commented Mar 21, 2020

Couple of things for debugging purposes that it took a while for me to notice:

1.) FreeBPX / Asterisk don't appear to tell you if it can't find the script (this was not the correct filename at that point)

DEBUG[24625][C-00000187] app_voicemail.c: Sent mail to <redacted> with command '/usr/sbin/sendmial.asterisk'

2.) If you do turn off removal of the temp directory to pipe the steam file in again:

# cat /tmp/astVM-XXXXXXXX/stream.org | /usr/sbin/sendmail.asterisk

IT WILL NOT APPEAR. There is a message-ID header in there, duplicates are ignored, at least by gmail - change it a bit each time.

3.) Errors from IBM are accessible in the audio.txt file in the created temp directory

@jtsage
Copy link
Author

jtsage commented Jul 31, 2025

  • updated for FreePBX17 / new voice models.
  • added syslog logging to mail.info (probably /var/log/mail.log)
  • moved the config stuff closer to the top, added a DEBUG flag to toggle file removal

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment