← All Tutorials

How to Configure ViciDial Answering Machine Detection (AMD)

ViciDial Administration Intermediate 14 min read #93

Master Asterisk's built-in AMD engine and implement production-grade answering machine detection in ViciDial to increase agent productivity, reduce wasted call time, and improve contact rates on outbound campaigns.

Prerequisites

Before configuring AMD in ViciDial, ensure you have:

Verify your current installation:

sudo asterisk -v
sudo mysql -u root -p -e "SELECT VERSION();"
grep -i "version" /usr/share/astguiclient/vicidial.conf | head -5

Understanding AMD (Answering Machine Detection)

What Is AMD?

Answering Machine Detection is an Asterisk application that analyzes audio patterns during the first few seconds of a call to determine whether a human answered or a voicemail/answering machine picked up. This allows ViciDial to:

How Asterisk AMD Works

Asterisk's AMD application listens to the initial audio after answer for:

  1. Silence - Machines typically have silence before greeting
  2. Voice patterns - Frequency analysis to distinguish human speech from recorded messages
  3. Speech/silence ratio - Humans vary speech patterns; machines are monotone
  4. Duration thresholds - Machines usually have longer initial silence periods

The engine compares these against configurable thresholds and returns a detection result: HUMAN, MACHINE, or NOTSURE.

ViciDial AMD Configuration Architecture

Configuration Layers

AMD in ViciDial operates across multiple layers:

  1. Asterisk dialplan level - /etc/asterisk/extensions-vicidial.conf
  2. ViciDial campaign settings - Web admin panel and vicidial_campaigns table
  3. Carrier/trunk configuration - /etc/asterisk/sip-vicidial.conf
  4. Application logic - /usr/share/astguiclient/ scripts and vicidial_log recording

Key ViciDial Tables for AMD

-- View campaign AMD settings
SELECT campaign_id, campaign_name, answering_machine_detect, 
       amd_machine_action, amd_human_action 
FROM vicidial_campaigns LIMIT 5;

-- Check call logs with AMD results
SELECT lead_id, caller_id_number, call_date, amd_result, 
       status, call_length 
FROM vicidial_log 
WHERE amd_result IS NOT NULL 
ORDER BY call_date DESC LIMIT 20;

-- View carrier AMD configuration
SELECT carrier_id, carrier_name, call_quality, sip_account 
FROM vicidial_carrier_log LIMIT 10;

Step 1: Enable AMD in Your Campaign

Access Campaign Settings

Log into ViciDial admin panel:

https://your-vicidial-ip/vicidial/admin.php

Navigate: Campaigns → Select Your Campaign → Edit Campaign → Call Parameters

Database Method (Recommended for Bulk Changes)

Connect to the asterisk database:

mysql -u root -p asterisk

Enable AMD for a specific campaign:

UPDATE vicidial_campaigns 
SET answering_machine_detect = 'Y',
    amd_machine_action = 'VOICEMAIL',
    amd_human_action = 'AGENT',
    amd_sensitivity = '2'
WHERE campaign_id = 'TESTCAMP';

-- Verify the change
SELECT campaign_id, answering_machine_detect, amd_machine_action, 
       amd_human_action, amd_sensitivity 
FROM vicidial_campaigns 
WHERE campaign_id = 'TESTCAMP';

Field Explanations:

Exit MySQL:

quit

Step 2: Configure Asterisk Dialplan

Locate the Dialplan File

sudo nano /etc/asterisk/extensions-vicidial.conf

Standard AMD Application Syntax

Add or modify the AMD application call in your outbound dialplan. Find the section for outbound calls (typically context from-internal):

[from-internal]
exten => _X.,1,NoOp(Starting outbound call for ${EXTEN})
exten => _X.,n,Set(TIMEOUT(absolute)=3600)
exten => _X.,n,GotoIf($["${answering_machine_detect}" = "Y"]?amd:noamd)
exten => _X.,n(amd),AMD(initial_silence=1500,greeting=1500,after_greeting_silence=800,total_analysis_time=5000,min_word_length=100,between_words_silence=50,silence_threshold=256)
exten => _X.,n,GotoIf($["${AMDSTATUS}" = "HUMAN"]?human:machine)
exten => _X.,n(human),Dial(SIP/${EXTEN}@carrier,45,m)
exten => _X.,n(machine),VoiceMail(u${EXTEN})
exten => _X.,n(noamd),Dial(SIP/${EXTEN}@carrier,45,m)

AMD Parameter Breakdown

AMD(
  initial_silence=1500,        # Silence before greeting starts (ms) - 1500ms = 1.5s
  greeting=1500,               # Max time to listen for greeting (ms)
  after_greeting_silence=800,  # Silence after greeting ends (ms)
  total_analysis_time=5000,    # Maximum time to run detection (ms)
  min_word_length=100,         # Min milliseconds for word (filter for noise)
  between_words_silence=50,    # Expected silence between words (ms)
  silence_threshold=256        # Audio level threshold for silence detection (0-32768)
)

Recommended Settings for Different Scenarios:

For aggressive detection (more false positives as human):

AMD(initial_silence=800,greeting=1200,after_greeting_silence=500,total_analysis_time=3000,min_word_length=80,between_words_silence=40,silence_threshold=256)

For conservative detection (more false negatives as machine):

AMD(initial_silence=2000,greeting=2000,after_greeting_silence=1000,total_analysis_time=6000,min_word_length=120,between_words_silence=60,silence_threshold=256)

For international calls (longer greeting times):

AMD(initial_silence=2500,greeting=2500,after_greeting_silence=1200,total_analysis_time=7000,min_word_length=100,between_words_silence=50,silence_threshold=256)

ViciDial's AMD Integration in Dialplan

ViciDial typically handles AMD through the vicidial_dial context. Find this section:

grep -n "vicidial_dial" /etc/asterisk/extensions-vicidial.conf | head -20

Locate and update the AMD section (usually around line 800-1200):

[vicidial_dial]
exten => 1,1,NoOp(ViciDial Dial Context - AMD Enabled)
exten => 1,n,Set(DIALGROUP=${CUT(DIALSTRING,^,1)})
exten => 1,n,Set(EXTENSION=${CUT(DIALSTRING,^,2)})
exten => 1,n,Set(answering_machine_detect=${amd_setting})

exten => 1,n,GotoIf($["${answering_machine_detect}" = "Y"]?doamd:nocheckamd)

exten => 1,n(doamd),NoOp(Running AMD with sensitivity: ${amd_sensitivity})
exten => 1,n,AMD(initial_silence=1500,greeting=1500,after_greeting_silence=800,total_analysis_time=5000,min_word_length=100,between_words_silence=50,silence_threshold=256)
exten => 1,n,Set(amd_result=${AMDSTATUS})
exten => 1,n,NoOp(AMD Result: ${amd_result})

exten => 1,n(nocheckamd),GotoIf($["${amd_result}" = "HUMAN"]?routehuman)
exten => 1,n,GotoIf($["${amd_result}" = "MACHINE"]?routemachine)
exten => 1,n(routehuman),NoOp(Routing to agent)
exten => 1,n,Dial(SIP/${EXTENSION}@${CARRIER},45,m)
exten => 1,n(routemachine),NoOp(Machine detected - applying action: ${amd_machine_action})
exten => 1,n,VoiceMail(u${EXTENSION})

Reload Asterisk After Changes

sudo asterisk -rx "dialplan reload"
sudo asterisk -rx "module reload app_amd"

Verify the reload was successful:

sudo asterisk -rx "dialplan show vicidial_dial@from-internal" | grep -i amd

Step 3: Configure Carrier/Trunk Settings

Edit SIP Configuration

sudo nano /etc/asterisk/sip-vicidial.conf

Ensure your carrier/trunk has appropriate settings for AMD:

[carrier_siptrunk]
type=peer
host=carrier.example.com
secret=yoursecret
username=youruser
fromuser=youruser
fromdomain=carrier.example.com
context=from-internal
disallow=all
allow=ulaw
allow=alaw
nat=yes
rtptimeout=600
rtpholdtimeout=3600
insecure=port,invite
reinvite=nodata

; AMD-specific settings
; Ensure codec matches to avoid audio quality issues
directmedia=no
; Important: Keep connection open for AMD audio analysis
dtmfmode=rfc2833

Reload SIP configuration:

sudo asterisk -rx "sip reload"

Step 4: Configure Machine Detection Actions

Understanding Machine Actions

When AMD detects a machine, you have three primary actions:

Option 1: VOICEMAIL (Drop Message)

UPDATE vicidial_campaigns 
SET amd_machine_action = 'VOICEMAIL' 
WHERE campaign_id = 'TESTCAMP';

Configure your voicemail drop message:

sudo nano /etc/asterisk/voicemail.conf

Add a context for ViciDial voicemail drops:

[vicidial]
; Voicemail drop box for machine-detected calls
1000 => 1234,ViciDial Machine Drop,[email protected],,|attach=yes|saycid=yes|sendvoicemail=yes|delete=no

Create the voicemail drop message file:

sudo mkdir -p /var/spool/asterisk/voicemail/vicidial/1000/INBOX
sudo chown -R asterisk:asterisk /var/spool/asterisk/voicemail/

Record and upload a custom message, or use this command to create via TTS:

echo "Your company name. Press 1 to schedule a callback or hang up." | \
  text2wave -o /var/spool/asterisk/voicemail/vicidial/1000/INBOX/msg0000.wav

Option 2: HANGUP (Disconnect Call)

UPDATE vicidial_campaigns 
SET amd_machine_action = 'HANGUP' 
WHERE campaign_id = 'TESTCAMP';

Useful for high-volume campaigns where you don't want to spend credits on machine messages.

Option 3: CALLBACK (Queue for Callback)

UPDATE vicidial_campaigns 
SET amd_machine_action = 'CALLBACK' 
WHERE campaign_id = 'TESTCAMP';

Requires callback queue configuration in ViciDial admin panel.

Configure Human Actions

When a human is detected, route to agent:

UPDATE vicidial_campaigns 
SET amd_human_action = 'AGENT' 
WHERE campaign_id = 'TESTCAMP';

Or send to voicemail if agent unavailable:

UPDATE vicidial_campaigns 
SET amd_human_action = 'VOICEMAIL' 
WHERE campaign_id = 'TESTCAMP';

Step 5: Adjust AMD Sensitivity

Sensitivity Levels

ViciDial uses 5 sensitivity levels (1-5):

Adjust via Database

UPDATE vicidial_campaigns 
SET amd_sensitivity = '2' 
WHERE campaign_id = 'TESTCAMP';

Fine-Tune with Asterisk Parameters

Modify the threshold values in your dialplan:

For higher sensitivity (fewer machines detected as human):

AMD(initial_silence=2000,greeting=1800,after_greeting_silence=1000,total_analysis_time=6000,min_word_length=120,between_words_silence=60,silence_threshold=256)

For lower sensitivity (more lenient):

AMD(initial_silence=1000,greeting=1200,after_greeting_silence=600,total_analysis_time=4000,min_word_length=80,between_words_silence=40,silence_threshold=256)

Step 6: Monitor AMD Performance

Real-Time Monitoring

Check AMD statistics in real-time:

sudo asterisk -rx "core show calls"

Monitor Asterisk logs specifically for AMD:

tail -f /var/log/asterisk/messages | grep AMD

Example output:

[2024-01-15 14:23:45] -- AMD: Detected HUMAN on channel SIP/1001-00001234
[2024-01-15 14:24:12] -- AMD: Detected MACHINE on channel SIP/1002-00001235
[2024-01-15 14:24:45] -- AMD: NOTSURE on channel SIP/1003-00001236

Query AMD Results from Database

Check detection accuracy for a date range:

SELECT 
  amd_result,
  COUNT(*) as call_count,
  ROUND(COUNT(*)*100.0/(SELECT COUNT(*) FROM vicidial_log 
    WHERE call_date >= DATE_SUB(NOW(), INTERVAL 7 DAY) 
    AND amd_result IS NOT NULL),2) as percentage
FROM vicidial_log 
WHERE call_date >= DATE_SUB(NOW(), INTERVAL 7 DAY) 
  AND amd_result IS NOT NULL
GROUP BY amd_result;

Expected output:

+----------+------------+------------+
| amd_result | call_count | percentage |
+----------+------------+------------+
| HUMAN    |       1245 |      68.50 |
| MACHINE  |        456 |      25.10 |
| NOTSURE  |        119 |       6.40 |
+----------+------------+------------+

Campaign-Specific AMD Analytics

SELECT 
  campaign_id,
  COUNT(*) as total_calls,
  SUM(CASE WHEN amd_result = 'HUMAN' THEN 1 ELSE 0 END) as humans,
  SUM(CASE WHEN amd_result = 'MACHINE' THEN 1 ELSE 0 END) as machines,
  SUM(CASE WHEN amd_result = 'NOTSURE' THEN 1 ELSE 0 END) as notsure,
  ROUND(AVG(call_length),2) as avg_call_length
FROM vicidial_log 
WHERE call_date >= DATE_SUB(NOW(), INTERVAL 1 DAY)
  AND amd_result IS NOT NULL
GROUP BY campaign_id
ORDER BY total_calls DESC;

Create AMD Performance Report View

CREATE VIEW amd_performance_daily AS
SELECT 
  DATE(call_date) as call_date,
  campaign_id,
  COUNT(*) as total_calls,
  ROUND(SUM(CASE WHEN amd_result = 'HUMAN' THEN 1 ELSE 0 END) * 100.0 / COUNT(*), 2) as human_percentage,
  ROUND(SUM(CASE WHEN amd_result = 'MACHINE' THEN 1 ELSE 0 END) * 100.0 / COUNT(*), 2) as machine_percentage,
  ROUND(SUM(CASE WHEN amd_result = 'NOTSURE' THEN 1 ELSE 0 END) * 100.0 / COUNT(*), 2) as notsure_percentage,
  ROUND(AVG(call_length), 2) as avg_call_length_seconds
FROM vicidial_log 
WHERE amd_result IS NOT NULL
GROUP BY DATE(call_date), campaign_id;

SELECT * FROM amd_performance_daily WHERE call_date >= DATE_SUB(NOW(), INTERVAL 7 DAY);

Step 7: Optimize Performance

CPU Impact

AMD analysis requires CPU resources. For high-volume systems:

# Check current load
top -b -n 1 | head -3

# Monitor Asterisk process
ps aux | grep asterisk | grep -v grep

Database Performance

AMD logging can increase database I/O. Optimize:

-- Add index on amd_result for faster queries
ALTER TABLE vicidial_log ADD INDEX idx_amd_result (amd_result);

-- Archive old AMD data
INSERT INTO vicidial_log_archive SELECT * FROM vicidial_log 
WHERE call_date < DATE_SUB(NOW(), INTERVAL 90 DAY);

DELETE FROM vicidial_log 
WHERE call_date < DATE_SUB(NOW(), INTERVAL 90 DAY);

-- Optimize table
OPTIMIZE TABLE vicidial_log;

Audio Codec Selection

For best AMD performance, use:

; In your sip-vicidial.conf carrier config
disallow=all
allow=ulaw
allow=alaw
; Avoid GSM or other compressed codecs

Adjust Analysis Time

If AMD is consuming too much CPU, reduce analysis time:

AMD(initial_silence=1500,greeting=1500,after_greeting_silence=800,total_analysis_time=3500,min_word_length=100,between_words_silence=50,silence_threshold=256)

This reduces from 5000ms to 3500ms maximum analysis time.

Troubleshooting

Issue 1: AMD Not Detecting Anything (All NOTSURE)

Symptoms: AMD runs but all results are NOTSURE

Diagnosis:

tail -f /var/log/asterisk/messages | grep -i notsure

Solutions:

  1. Verify AMD module is loaded:
sudo asterisk -rx "module show like amd"

Output should show:

Module                         Description                      Use Count
app_amd.so                     Answering Machine Detection      0
  1. Check if AMD settings match campaign config:
SELECT campaign_id, answering_machine_detect, amd_sensitivity, 
       amd_machine_action, amd_human_action 
FROM vicidial_campaigns 
WHERE campaign_id = 'TESTCAMP';
  1. Lower sensitivity level:
UPDATE vicidial_campaigns 
SET amd_sensitivity = '1' 
WHERE campaign_id = 'TESTCAMP';
  1. Increase analysis time in dialplan:
AMD(initial_silence=2500,greeting=2500,after_greeting_silence=1200,total_analysis_time=7000,min_word_length=100,between_words_silence=50,silence_threshold=256)

Issue 2: Too Many False Positives (Machines Detected as Human)

Symptoms: AMD marks voicemail boxes as HUMAN, agents connect to machines

Solutions:

  1. Increase sensitivity:
UPDATE vicidial_campaigns 
SET amd_sensitivity = '4' 
WHERE campaign_id = 'TESTCAMP';
  1. Adjust dialplan parameters to be more conservative:
AMD(initial_silence=2000,greeting=2000,after_greeting_silence=1000,total_analysis_time=6000,min_word_length=120,between_words_silence=60,silence_threshold=256)
  1. Increase initial silence detection:
AMD(initial_silence=2500,greeting=2000,after_greeting_silence=1000,total_analysis_time=5500,min_word_length=100,between_words_silence=50,silence_threshold=256)

Issue 3: Too Many False Negatives (Humans Detected as Machine)

Symptoms: Real people being treated as machines, agents missing live calls

Solutions:

  1. Decrease sensitivity:
UPDATE vicidial_campaigns 
SET amd_sensitivity = '1' 
WHERE campaign_id = 'TESTCAMP';
  1. Adjust to more aggressive detection:
AMD(initial_silence=1200,greeting=1200,after_greeting_silence=600,total_analysis_time=4000,min_word_length=80,between_words_silence=40,silence_threshold=256)
  1. Reduce min_word_length to catch softer human voices:
AMD(initial_silence=1500,greeting=1500,after_greeting_silence=800,total_analysis_time=5000,min_word_length=70,between_words_silence=50,silence_threshold=256)

Issue 4: AMD Not Running at All

Symptoms: Campaign has AMD enabled but amd_result column is always NULL

Check the dialplan context is correct:

grep -A 20 "answering_machine_detect" /etc/asterisk/extensions-vicidial.conf

Verify campaign setting:

SELECT campaign_id, answering_machine_detect 
FROM vicidial_campaigns 
WHERE campaign_id = 'TESTCAMP';

Reload dialplan:

sudo asterisk -rx "dialplan reload"
sudo asterisk -rx "module reload app_amd"
sudo service asterisk restart

Check for errors in logs:

grep -i "error\|warning" /var/log/asterisk/messages | tail -20

Issue 5: AMD Causing Call Delays

Symptoms: Noticeable delay before agent answer or ringback

Solutions:

  1. Reduce total_analysis_time:
AMD(initial_silence=1200,greeting=1200,after_greeting_silence=600,total_analysis_time=3000,min_word_length=100,between_words_silence=50,silence_threshold=256)
  1. Reduce greeting time:
AMD(initial_silence=1000,greeting=1000,after_greeting_silence=500,total_analysis_time=3500,min_word_length=100,between_words_silence=50,silence_threshold=256)
  1. Check Asterisk CPU - if high, enable AMD on fewer campaigns:
top -p $(pgrep -f "asterisk -f")

Issue 6: Database Filling Up with AMD Logs

Symptoms: /var partition nearly full, slow database queries

Solution - Archive and purge old AMD data:

# First, create backup
mysqldump -u root -p asterisk vicidial_log > /backup/vicidial_log_backup_$(date +%Y%m%d).sql

# Then, in MySQL
mysql -u root -p asterisk
-- Archive calls older than 90 days
INSERT INTO vicidial_log_archive 
SELECT * FROM vicidial_log 
WHERE call_date < DATE_SUB(NOW(), INTERVAL 90 DAY);

-- Delete archived records
DELETE FROM vicidial_log 
WHERE call_date < DATE_SUB(NOW(), INTERVAL 90 DAY);

-- Optimize table
OPTIMIZE TABLE vicidial_log;

-- Check size reduction
SELECT 
  ROUND(((data_length + index_length) / 1024 / 1024), 2) as size_mb
FROM information_schema.tables 
WHERE table_schema = 'asterisk' 
  AND table_name = 'vicidial_log';

Step 8: A/B Testing AMD Performance

Set Up Two Campaigns for Testing

Campaign 1 (Control - AMD Disabled):

UPDATE vicidial_campaigns 
SET answering_machine_detect = 'N' 
WHERE campaign_id = 'TESTCAMP_CONTROL';

Campaign 2 (Test - AMD Enabled):

UPDATE vicidial_campaigns 
SET answering_machine_detect = 'Y',
    amd_machine_action = 'VOICEMAIL',
    amd_human_action = 'AGENT',
    amd_sensitivity = '2'
WHERE campaign_id = 'TESTCAMP_AMD';

Compare Results

SELECT 
  campaign_id,
  COUNT(*) as total_calls,
  ROUND(AVG(call_length), 2) as avg_talk_time,
  ROUND(SUM(CASE WHEN status = 'SALE' THEN 1 ELSE 0 END) * 100.0 / COUNT(*), 2) as conversion_rate,
  ROUND(SUM(CASE WHEN status IN ('SALE','CALLACK') THEN 1 ELSE 0 END) * 100.0 / COUNT(*), 2) as success_rate
FROM vicidial_log 
WHERE campaign_id IN ('TESTCAMP_CONTROL', 'TESTCAMP_AMD')
  AND call_date >= DATE_SUB(NOW(), INTERVAL 7 DAY)
GROUP BY campaign_id;

Expected results with AMD enabled:

Best Practices and Recommendations

1. Start Conservative

Begin with AMD enabled on one campaign at lower sensitivity (3-4) to validate detection accuracy before rolling out widely.

2. Monitor Accuracy Rates

Aim for 85-95% overall accuracy. Review NOTSURE results weekly:

SELECT call_id, phone_number, amd_result, status, call_length 
FROM vicidial_log 
WHERE amd_result = 'NOTSURE' 
  AND call_date >= DATE_SUB(NOW(), INTERVAL 7 DAY) 
ORDER BY call_date DESC 
LIMIT 50;

3. Combine AMD with Other Strategies

4. Regular Parameter Tuning

Adjust AMD parameters quarterly based on:

5. Failover Strategy

Ensure AMD failures don't break the call:

exten => 1,n,GotoIf($["${AMDSTATUS}" = "HUMAN"]?human)
exten => 1,n,GotoIf($["${AMDSTATUS}" = "MACHINE"]?machine)
exten => 1,n(human),Dial(SIP/${EXTENSION}@${CARRIER},45,m)
exten => 1,n(machine),VoiceMail(u${EXTENSION})

Always have a default action if AMD fails.

6. Logging and Auditing

Enable detailed logging:

[general]
verbose=3
debug=3

This generates more logs but aids troubleshooting.

Summary

Answering Machine Detection in ViciDial significantly improves outbound campaign efficiency by automatically filtering machine-answered calls from human-answered calls. The configuration spans three areas:

  1. Campaign Settings - Enable AMD and set machine/human actions via vicidial_campaigns table
  2. Asterisk Dialplan - Configure AMD application with appropriate parameters in extensions-vicidial.conf
  3. Monitoring & Optimization - Query vicidial_log table for AMD results and continuously tune parameters

Key takeaways:

With proper AMD configuration, expect:

Regularly review your AMD performance metrics, gather agent feedback, and adjust parameters quarterly. AMD is not a "set and forget" feature—continuous optimization yields the best results for your specific calling profile and contact list characteristics.

Stuck on something specific?

Book a free 30-minute call. I run ViciDial centers across 3 countries and can usually unblock your setup in one session — or build it for you.

Book a Free Consultation