Guide

FreeSWITCH AMD: mod_avmd, mod_vmd and Speech-Based Detection Compared

FreeSWITCH has shipped two voicemail detection modules and most dialers built on it use neither well. What mod_vmd and mod_avmd actually detect, where each fails on real calls, how to run them in a dialplan, and when a speech-based detector in front of them is the right move.

Marketing Team

VM Hunter

November 12, 2026
9 min read
FreeSWITCH AMD: mod_avmd, mod_vmd and Speech-Based Detection Compared

FreeSWITCH does not have an answering machine detector in the sense that Asterisk has app_amd. What it has is two modules that detect the beep at the end of a voicemail greeting, one old and one newer, and a set of audio-streaming modules that let you hand the call to something smarter. Which of those you use decides how your outbound dialer behaves on the one call in three that does not reach a person.

This post explains what mod_vmd and mod_avmd actually do, how they are wired into a dialplan, the calls they get wrong, and what a speech-based detector adds when you put it in front of them.

What a beep detector does and does not do

Both FreeSWITCH modules work on the same principle. A voicemail system ends its greeting with a tone, usually a single frequency around one kilohertz lasting a few hundred milliseconds. The module watches the audio for that tone and fires an event when it hears one.

That is a different job from answering machine detection. A beep detector tells you the greeting has finished. It does not tell you whether there was a greeting, whether a person answered instead, or what to do during the five to twelve seconds of greeting before the tone arrives. A dialer that only has a beep detector has to make the human-or-machine decision some other way, usually by waiting for the beep and assuming anything that produced one was a machine.

The practical consequence is that a FreeSWITCH dialer running only mod_avmd connects every call to an agent at answer and lets the agent discover the voicemail, or holds every call until either a beep arrives or a timeout passes, during which a live person hears silence. Neither is what anyone wants, which is why FreeSWITCH-based dialers tend to bolt on an external detector.

mod_vmd: the original

mod_vmd was the first voicemail detection module in FreeSWITCH. It looks for a sustained tone in the audio and raises a vmd::beep event when it finds one. It is simple, light and works well on the classic North American mailbox beep.

It has been superseded and in most builds is either absent or marked deprecated. Its weaknesses are the ones you would expect from a tone detector written for one kind of beep: it misses the double tones and chirps some carriers use, it can be fooled by hold music that holds a note, and it has no idea what happened before the tone.

If you are running it today, the only reason to keep doing so is that it is already wired into a dialplan you do not want to touch. For anything new, use mod_avmd.

mod_avmd: advanced voicemail detection

mod_avmd replaced mod_vmd with a more robust detector. Instead of a single frequency check it uses a frequency-estimation algorithm over a sliding window, which lets it detect a wider range of beep tones and reject more of the false triggers that caught mod_vmd. It is configurable: you can set the detection window, the frequency range, the minimum tone duration and whether it fires once or keeps listening.

In a dialplan it runs as an application on the channel:

<action application="avmd_start" data="inbound_channel=0,outbound_channel=1,detection_mode=1"/>

and raises an avmd::beep event (or sets a channel variable, depending on configuration) when a tone is detected. Your dialer or ESL application listens for the event and decides what to do: play a message, hang up, or mark the lead.

mod_avmd is a good beep detector. On a list that is mostly consumer mobiles with standard carrier mailboxes, it will catch most tones. What it still does not do is anything before the tone.

Where beep detection fails on real calls

Here are the calls, from real outbound traffic, that a beep-only approach gets wrong.

The greeting without a beep. Some business mailboxes and many carrier "the customer is not available" messages end in silence or a click, not a tone. mod_avmd never fires. The dialer waits for its timeout, which it spends either holding a line open or holding an agent.

The live person who sounds like a greeting. A receptionist answering with the company name, a department and "how may I direct your call" produces eight seconds of continuous speech. A beep detector does not care, because it is only listening for a tone, but whatever the dialer does with the call before the tone decides whether that receptionist hears an agent or dead air.

The beep that is not a mailbox. Call-waiting tones, fax handshakes and some IVR prompts contain frequencies in the detection range. With the detection window set wide to catch more mailboxes, these come through as beeps.

Call screening. The iOS 26 "record your name and reason for calling" prompt and Google Call Screen answer the call with a sentence, then wait. There is no beep. A beep-only dialer either times out or connects an agent to a robot asking who they are. A speech-based detector hears the sentence and labels it as screening, which matters because there is a person behind it reading a transcript.

The disconnected number. Carriers increasingly answer dead numbers with a recorded message rather than a SIP error. The message may end in a tone. mod_avmd fires, the dialer plays a voicemail drop into a recording that will never be heard, and the lead is dispositioned as a machine rather than retired.

A real-world example: the hosted dialer with a two-second hold

A hosted dialer vendor built on FreeSWITCH used mod_avmd and a rule of their own: hold every answered call for two seconds, and if no beep arrived, connect it to an agent. The reasoning was that most greetings are longer than two seconds so most machines would be caught by the timeout, and most people say hello within two seconds.

What the agents reported was the opposite. People who answered and said "Hello?" waited two seconds in silence and often hung up before the agent came on. Voicemail greetings, which are longer than two seconds, reached agents constantly because the beep had not yet arrived at the two-second mark. The vendor's own call logs showed machines reaching agents on about a third of answered calls, and a measurable rise in callers hanging up during the hold.

They solved it by streaming the first two seconds of audio out through mod_audio_stream to a speech-based detector, acting on its HUMAN or MACHINE verdict, and keeping mod_avmd only for timing the voicemail drop after a MACHINE result. Machines reaching agents dropped to single digits, and the hold went away because a HUMAN verdict connects the agent immediately.

Putting a speech-based detector in front of mod_avmd

The pattern that works on FreeSWITCH is a division of labour. The speech-based detector decides what answered, in about two seconds, from the words and tones in the opening audio. mod_avmd then handles the beep timing for the calls that were machines.

FreeSWITCH has two modules that make the streaming part straightforward: mod_audio_fork from the drachtio project, and mod_audio_stream. Both fork the channel's audio to a WebSocket. The VM Hunter FreeSWITCH client is a Lua script and a dialplan extension that work with either, detect which one is loaded, stream the callee's audio from the moment of answer, and set AMDSTATUS and AMDCAUSE on the channel when the verdict returns. The dialplan then branches:

<action application="lua" data="vmhunter_amd.lua"/>
<condition field="${AMDSTATUS}" expression="^HUMAN$">
  <action application="transfer" data="agent_queue XML default"/>
  <anti-action application="transfer" data="machine_handling XML default"/>
</condition>

In the machine branch, AMDCAUSE tells you which kind of machine. MACHINE_BEEP or voicemail wording means start mod_avmd and drop the message after the tone. DISCONNECT means hang up and retire the lead. CALLGUARD_PHRASE means a person is reading a screening transcript: play a one-line intro naming your company and transfer to an agent.

The whole thing is one Lua script, one extension and a few condition blocks. The full setup, with both streaming modules covered, is in the FreeSWITCH integration guide, and the client is open source so you can read it before it touches a production switch.

Choosing between the options

Stay with mod_avmd alone if your list is almost entirely consumer mobiles with standard mailboxes, you do not run voicemail drop, and your agents are fine discovering the occasional greeting. It costs nothing and it is already there.

Add a speech-based detector if agents are hearing voicemails, if live people are complaining about dead air, if you want voicemail drop to land reliably, or if call screening is showing up in your logs. The streaming modules are mature, the client is small, and the free plan covers five thousand calls a month, which is enough to run both side by side on one campaign for a week and compare the dispositions against the recordings.

Keep both in the end state. The speech-based verdict decides the routing. mod_avmd times the drop.

FAQ

Is mod_vmd still supported? It is deprecated in favour of mod_avmd and absent from many current builds. If your dialplan references it, plan to move to mod_avmd.

Does mod_avmd detect a human answer? No. It detects a tone. The human-or-machine decision has to come from somewhere else, either a timeout rule in your dialer or an external detector.

Which streaming module should I use, mod_audio_fork or mod_audio_stream? Either. mod_audio_fork is part of the drachtio modules and is widely deployed. mod_audio_stream is a lighter standalone module. The VM Hunter client works with both and detects which is loaded.

What audio format does a speech-based detector need from FreeSWITCH? Eight kilohertz, sixteen-bit, mono PCM, which is what both streaming modules produce from a telephony channel. No transcoding is needed.

How much audio leaves the switch? About two seconds per answered call, and only after answer. If policy prevents any audio leaving the network, an on-premises version of the detector runs on the same host as FreeSWITCH.

Can I run this on a FreeSWITCH-based commercial dialer? If the vendor exposes the dialplan or an ESL hook where you can run a Lua script before agent transfer, yes. If they do not, ask them: several hosted dialers have added speech-based detection as a configurable option after customers asked.

FreeSWITCH gives you excellent building blocks and no opinion about how to use them. For answering machine detection, the combination that holds up on real traffic is a speech-based verdict for routing and mod_avmd for the beep. The integration guide has the full dialplan.