Skip to content

epotyom/asterisk-programmable-musiconhold

Repository files navigation

Asterisk - extended (programmable) music on hold

What is it?

This program allowes you to extend asterisk music on hold functions. Current realization supports:

  • Playing backgound music (when voice information begins, music fades out, after speech ends music fades in back)
  • Change background music on key 3 (DTMF)
  • Playing personal information (account balance) retrived from some billing by customer phone number, on dtfm 2 signal.
  • Playing some voice information, every file will be played one time, also some files (music/advices/first*) will be played in alphabetical order, other files (music/advices/middle*) will be played in random order.
  • Advices could be played only at the morning, at the evening, or other time
  • Playing queue position once in a while or on dtfm key press

All this functions are customized for one organization. But this program gives you a template, that you could rewrite for your purposes.

How it works?

Asterisk allowes to get musiconhold flow from some application, that is able to stream sound to its stdout in format like that:

# ffprobe ./mono-8000.wav 2>&1 | grep Stream
Stream #0:0: Audio: pcm_s16le ([1][0][0][0] / 0x0001), 8000 Hz, 1 channels, s16, 128 kb/s

It is python script, that connects to asterisk by AMI and reads DTFM events on channel that is in queue. Than this script runs Liquidsoap script, that mixes music and sounds and streams it to its stdout.

Also python script can retrive some information from your billing web API (for example, user account state info), and put it to the liquidsoap playlist.

Installation

You have to create musiconhold class with custom mode. For example, in musiconhold.conf:

[programmable]
mode=custom
application = /path/to/script/run.sh

By default, asterisk runs musiconhold class once first channel connected to it, and then all other channels connect to the same sound stream to save CPU usage. It's not good for us, because we want every channel listen to its own radio. So, we have to turn off this feature in musiconhold.conf, [general] section:

[general]
cachertclasses=no

Also in dialplan, before queue call, you should set some environment variables and musiconhold class, for example:

exten = s,1,Set(CHANNEL(musicclass)=programmable)
exten = s,n,Set(ENV(PHONE)=${CALLERID(num)})
exten = s,n,Set(ENV(UNIQUEID)=${UNIQUEID})
exten = s,n,Set(ENV(CHANNEL)=${CHANNEL})
exten = s,n,Queue(...

Also you need table to save last music choosen by user:

CREATE TABLE `queue_music` (
  `id` int(10) NOT NULL AUTO_INCREMENT,
  `src` char(15) DEFAULT NULL,
  `music_class` smallint(2) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `src` (`src`)
) ENGINE=InnoDB AUTO_INCREMENT=753748 DEFAULT CHARSET=latin1

Configuration

Rename config-example.py to config.py and change it (there are comments in this file)

Customization

All python logic is in the runner.py file.

Liquidsoap script also generated by python (it is in functions.py file, function get_liquidsoap_script)

Feel free to write project issues if you need some help

Known problems

  1. Enviromnent variables (channel,phone number and callid) that asterisk sets are global, that means that if 2 or more users enters queues simultaniously, there could be collision in this variables and user could listen to others information. But I was testing it a lot and never got this situation. Also there is dirty workaround for this problem - you could generate realtime musiconhold class for every channel that eneters queue.

  2. Asterisk 11.7.0 craches with segmantation fault once in a while with segmentation fault in res_musiconhold.so. I've updated it to 11.19 version (builded from source), and this problem was solved.

About

Asterisk extended (programmable) music-on-hold for queues

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published