Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
Asterisk voicemail mailcmd script for VM transcription
# sendmail-bluemix
# current verison of this script:
# Original source created by N. Bernaerts:
# modified per:
# Notes: This is a script modified from the original to work with a FreePBX Distro PBX so that email notifications sent from
# Asterisk voicemail contain a speech to text trasncription provided by IBM Bluemix
# License: There are no explicit license terms on the original script or on the blog post with modifications
# I'm assumig GNU/GPL2+ unless notified otherwise by copyright holder(s)
# Usage: copy this file to /usr/sbin/ set ownership to asterisk:asterisk and make it executable.
# In the [general] section of /etc/asterisk/voicemail.conf set mailcmd=/usr/sbin/sendmail-bluemix
# This script also uses dos2unix, ensure it is executable by the asterisk user (chmod 777)
# Specify your IBM Bluemix API key and URL on the lines noted below
# Version History:
# 2017-09-17 Initial commit by lgaetz, working but unpolished
# 2017-09-18 Original attachment added to email
# 2017-09-18 fixed problem with email without attachments
# 2020-04-16 COVID-19 edition - updated to use API key using method from github user @jtsage
# Specify IBM Bluemix API credentials
# follow instructions here to get key and url
# key is long string separated by underscore(s). API_OPTS assumes US english, but there are many other language options available
# see full API reference at:
# set PATH
# save the current directory
pushd .
# create a temporary directory and cd to it
TMPDIR=$(mktemp -d)
# dump the stream to a temporary file
cat >>
# get the boundary
BOUNDARY=$(grep "boundary=" | cut -d'"' -f 2)
# if mail has no boundaries, assume no attachment
if [ "$BOUNDARY" = "" ]
# send the original stream
# cut the original stream into parts
# stream.part - header before the boundary
# stream.part1 - header after the bounday
# 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}'
# 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. Must use "Narrowband" (aka 8k) model since WAV is 8k sample
# Send WAV to Watson Speech to Text API. Must use "Narrowband" (aka 8k) model since WAV is 8k sample
curl -s $CURL_OPTS -k -u "apikey:$API_KEY" -X POST \
--limit-rate 40000 \
--header "Content-Type: audio/wav" \
--data-binary @stream.part3.wav \
"$API_URL$API_OPTS" 1>audio.txt
# Extract transcript results from JSON response
TRANSCRIPT=`cat audio.txt | grep transcript | sed 's#^.*"transcript": "##g' | sed 's# "$##g'`
# generate first part of mail body, converting it to LF only
mv stream.part
cat stream.part1 >>
sed '$d' < stream.part2 >>
# beginning of transcription section
echo "--- Automated transcription result ---" >>
# append result of transcription
echo "$TRANSCRIPT" >>
# end of message body
tail -1 stream.part2 >>
# add orig attachment
cat stream.part3 >>
# append end of mail body, converting it to LF only
echo "" >> stream.tmp
echo "" >> stream.tmp
cat stream.part4 >> stream.tmp
dos2unix -o stream.tmp
cat stream.tmp >>
# send the mail thru sendmail
cat | sendmail -t
# go back to original directory
# remove all temporary files and temporary directory
rm -Rf $TMPDIR
Copy link

jtsage commented Mar 15, 2022

Haha. good timing, I too just got the annoucement from watson.

Copy link

lgaetz commented Jun 16, 2022

Many STT models being deprecated 2022-09-15 including "en-US_NarrowbandModel" which this script currently relies on. Needs to be updated, further reading here.

Copy link

realtoft123 commented Sep 13, 2022

Just change the API_OPTS="/v1/recognize?model=en-US_NarrowbandModel" line to API_OPTS="/v1/recognize?model=en-US_Telephony", and it works fine.
See here:
Also for the non-English users, here is a list of speech models:

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