← All Tutorials

Asterisk Codec Negotiation — G.711 vs G.729 vs Opus

Infrastructure & DevOps Intermediate 13 min read #56

Master codec selection and negotiation strategies for ViciDial deployments to optimize call quality, bandwidth, and server performance across different carrier and endpoint configurations.

Prerequisites

Before following this tutorial, ensure you have:

Understanding Codec Negotiation Fundamentals

What is Codec Negotiation?

Codec negotiation is the process by which two SIP endpoints determine which audio compression algorithm they will use for a call. When a call is initiated, the caller sends an SDP (Session Description Protocol) offer listing all codecs it supports, ordered by preference. The callee responds with an SDP answer, selecting the first codec from the offer that it also supports.

In ViciDial environments, this negotiation happens at three critical points:

  1. Agent to Asterisk (softphone or hardphone)
  2. Asterisk to Carrier (outbound SIP trunk)
  3. Carrier to Remote Party (destination network)

Misaligned codec preferences cause unnecessary transcoding—consuming CPU and degrading quality. Understanding and controlling this negotiation is essential for production deployments.

Why Codec Selection Matters in ViciDial

ViciDial call centers operate under strict constraints:

Choosing G.711 everywhere means crystal-clear calls but 64 kbps per leg. Choosing G.729 everywhere saves bandwidth but requires licensing. Opus offers the best compression with modern quality but requires modern endpoints.

The Three Primary Codecs Explained

G.711 (μ-Law and A-Law)

Technical specs:

Advantages:

Disadvantages:

ViciDial use case: Local carrier trunks, LAN-based agents, high-bandwidth WAN links, premium customer accounts.

G.729

Technical specs:

Advantages:

Disadvantages:

ViciDial use case: Remote agents over internet, international calls, bandwidth-constrained carriers, cost-sensitive operations.

Opus

Technical specs:

Advantages:

Disadvantages:

ViciDial use case: Cloud-based carrier connections (VoIP.ms, Twilio, Bandcamp), modern SIP endpoints, internal trunk connections, WebRTC integration.

Configuring Codec Preferences in Asterisk

Step 1: Understanding Asterisk Codec Configuration

Asterisk defines codecs in several places with a hierarchy:

Global preference (sip.conf) 
    ↓
Peer/User level (sip-vicidial.conf)
    ↓
Outbound proxy/carrier level
    ↓
Actual negotiation (what both sides support)

Step 2: Edit Global SIP Configuration

Navigate to /etc/asterisk/sip.conf and locate the [general] section:

[general]
context=default
allowguest=no
nat=force_rport,comedia
srvlookup=yes
udpbindaddr=0.0.0.0

; Codec configuration - order matters (top = preferred)
disallow=all
allow=g711u
allow=g711a
allow=g729
allow=opus

; Quality-of-service settings
tos_sip=cs3
tos_audio=ef
cos_sip=3
cos_audio=5

; Performance tuning
maxcallbitrate=384
videosupport=no

The disallow=all followed by specific allow statements creates an explicit whitelist. The order in allow statements determines preference order.

Step 3: Configure ViciDial-Specific SIP Peers

Edit /etc/asterisk/sip-vicidial.conf. This file is generated by ViciDial's admin interface but can be manually tweaked.

For internal agent extensions:

[6000]
type=friend
context=vicidial
host=dynamic
nat=force_rport,comedia
disallow=all
allow=opus
allow=g711u
allow=g711a
allow=g729
secret=PASSWORD123
mailbox=6000@vicidial
port=5060
qualify=yes
qualifyfreq=30
defaultuser=6000

For carrier trunks (outbound):

[carrier-outbound]
type=peer
host=sip.carrier.com
port=5060
context=from-carriers
nat=no
insecure=port,invite
disallow=all
allow=g711u
allow=g729
secret=CARRIER_SECRET
fromuser=YOUR_DID
fromdomain=sip.carrier.com
canreinvite=no
directmedia=no
rtptimeout=60
rtpholdtimeout=300

For internal Asterisk-to-Asterisk trunks:

[internal-remote-pbx]
type=friend
host=10.20.30.40
port=5060
context=from-internal-trunks
nat=no
disallow=all
allow=opus
allow=g711u
canreinvite=yes
directmedia=yes

Step 4: Create Codec-Specific Carrier Configurations

In production, you'll often have multiple carriers with different codec support. Create separate peer definitions:

; Carrier A: Supports G.711 and G.729
[carrier-a-main]
type=peer
host=sip1.carriera.com
disallow=all
allow=g711u
allow=g729
secret=CARRIER_A_SECRET
fromuser=ACCOUNT_ID_A

; Carrier B: Opus-native carrier (lower cost)
[carrier-b-premium]
type=peer
host=api.voipprovider.io
disallow=all
allow=opus
allow=g711u
secret=CARRIER_B_SECRET

; Fallback carrier: Only G.711 (legacy)
[carrier-legacy]
type=peer
host=sip.oldcarrier.com
disallow=all
allow=g711u
secret=LEGACY_SECRET

Step 5: Configure Dialplan for Codec Selection

Edit /etc/asterisk/extensions-vicidial.conf to implement codec routing logic:

[vicidial-inbound]
exten => _X.,1,Verbose(1,Incoming call from ${CALLERID(num)} to ${EXTEN})
same => n,Set(CHANNEL(hangup_handler_push)=vicidial-cleanup,s,1)
same => n,Gosub(vicidial-agent-routing,${EXTEN},1)

[vicidial-outbound-routing]
; Route to carrier based on destination pattern and codec capability
exten => _1NXXNXXXXXX,1,Verbose(2,Outbound: ${EXTEN} via smart routing)
same => n,Set(DEST=${EXTEN})
same => n,GotoIf($["${DEST:0:3}" = "011"]?international:domestic)

exten => international,1,Verbose(2,International call - using G.729)
same => n,Dial(SIP/carrier-b-premium/${DEST},60,tT)
same => n,Hangup()

exten => domestic,1,Verbose(2,Domestic call - using G.711)
same => n,Dial(SIP/carrier-a-main/${DEST},60,tT)
same => n,Hangup()

Practical Configuration Strategies

Strategy 1: High-Quality LAN Deployment

Scenario: Call center with 50 agents on the same network, gigabit backbone, premium carrier.

; /etc/asterisk/sip.conf [general]
disallow=all
allow=g711u
allow=g711a

; /etc/asterisk/sip-vicidial.conf [agent-extensions]
disallow=all
allow=g711u
allow=g711a

; /etc/asterisk/sip-vicidial.conf [carriers]
disallow=all
allow=g711u
allow=g729

Why: G.711 throughout the LAN provides maximum quality and zero transcoding. Carriers offer G.729 as fallback.

Bandwidth consumption: 1 call = 128 kbps (64 kbps each direction + overhead)

Strategy 2: Cloud-Based Remote Agents

Scenario: 100 remote agents on internet connections, cost-sensitive, modern VoIP provider.

; /etc/asterisk/sip.conf [general]
disallow=all
allow=opus
allow=g729
allow=g711u

; /etc/asterisk/sip-vicidial.conf [agent-extensions]
disallow=all
allow=opus
allow=g729
allow=g711u

; /etc/asterisk/sip-vicidial.conf [carriers]
disallow=all
allow=opus
allow=g711u

Why: Opus's variable bitrate adapts to network conditions. Falls back to G.729 for older softphones.

Bandwidth consumption: 1 call = 40-80 kbps average (Opus adapts), or 72 kbps minimum (G.729)

Strategy 3: Multi-Carrier Optimization

Scenario: 30 agents, multiple carriers with different codec support, mixed domestic/international.

Create carrier-specific profiles in a routing context:

[determine-carrier]
exten => _1NXXNXXXXXX,1,Verbose(2,Determining carrier for ${EXTEN})

; Domestic US routing (premium carrier supports all codecs)
same => n,GotoIf($["${EXTEN:0:1}" = "1"]?us-domestic)

; International routing (G.729 only)
same => n,GotoIf($["${EXTEN:0:3}" = "011"]?intl)

exten => us-domestic,1,Set(CARRIER=carrier-primary)
same => n,Set(CODEC_PREF=g711u)
same => n,Return()

exten => intl,1,Set(CARRIER=carrier-intl-gcc)
same => n,Set(CODEC_PREF=g729)
same => n,Return()

Monitoring and Debugging Codec Negotiation

Check Active Codec on Running Call

asterisk -rx "sip show channels"

Output shows connected calls with negotiated codecs:

Peer             Call ID      Duration  Recv: Format           Send: Format           
AGENT-6001       abc123@pbx   00:01:23  (opus)                 (opus)
carrier-a        xyz789@sip   00:02:45  (g729)                 (g729)

Detailed SIP Channel Information

asterisk -rx "sip show channel SIP/6001-00000001"

Returns:

Channel: SIP/6001-00000001
From: <sip:6001@10.0.0.50>
To: <sip:1234567890@sip.carrier.com>
Codecs: (g711u|g729)
Non-Codec Capabilities: (nothing)
Dtmf Mode: rfc2833
SIP Options: replaces, timer
Status: Up (CallID: abc@pbx, VoiceQuality: 0)
Codec Order (Outbound): g711u(64000), g729(8000)
Codec Order (Inbound): g711u(64000), g729(8000)

Packet-Level Inspection

Use ngrep to see actual SDP offer/answer:

sudo ngrep -W byline 'INVITE|200 OK|SDP' 'host 10.0.0.50 and port 5060'

Look for the m=audio line:

m=audio 15000 RTP/AVP 0 18 97
a=rtpmap:0 PCMU/8000
a=rtpmap:18 G729/8000
a=rtpmap:97 opus/48000

Numbers (0, 18, 97) correspond to codec payload types. First listed is preferred.

ViciDial-Level Logging

Enable verbose logging in Asterisk:

asterisk -rx "sip set debug on"
asterisk -rx "core set verbose 3"

Tail logs:

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

Check Transcoding Load

Monitor CPU usage during calls with transcoding:

asterisk -rx "core show system uptime"
asterisk -rx "core show threads"

Compare CPU with and without transcoding to quantify impact.

ViciDial Integration Points

Carrier Configuration via Admin Interface

In ViciDial web admin (/vicidial/admin.php):

  1. Go to Carrier ManagementAdd/Edit Carriers
  2. Locate the Preferred Codec dropdown
  3. Select primary codec (usually G711U for standard, G729 for savings)

The admin interface writes to vicidial_carrier_list table:

SELECT carrier_id, carrier_name, allow_codec FROM vicidial_carrier_list;

Example output:

carrier_id | carrier_name           | allow_codec
-----------|------------------------|-------------
1          | Primary Carrier        | G711U,G729
2          | International Gateway  | G729
3          | Premium VoIP Provider  | OPUS,G711U

Agent Codec Preferences

Agent-specific preferences are stored in vicidial_users table:

SELECT user_id, full_name, preferred_codec FROM vicidial_users WHERE user_id='6001';

Manually set codec preference (if admin interface doesn't support):

UPDATE vicidial_users SET preferred_codec='G729' WHERE user_id='6001';

Call Quality Tracking

After calls complete, check vicidial_log table for quality indicators:

SELECT 
  unique_id, 
  user, 
  call_date, 
  call_duration, 
  codec_used,
  mos_score
FROM vicidial_log 
WHERE call_date >= DATE_SUB(NOW(), INTERVAL 1 DAY)
ORDER BY call_date DESC 
LIMIT 20;

(Note: MOS scoring requires additional quality monitoring modules)

Reload Configuration Without Restart

After modifying codec settings, reload Asterisk without dropping calls:

asterisk -rx "sip reload"

Verify changes applied:

asterisk -rx "sip show peers" | grep -A5 "carrier-a-main"

Troubleshooting Codec Negotiation

Problem 1: One-Way Audio or No Audio

Symptom: Call connects but one or both parties hear nothing.

Root cause: Endpoints support different codecs; Asterisk lacks transcoding permission.

Diagnosis:

asterisk -rx "sip show channel SIP/6001-00000001" | grep Codecs

If output shows Codecs: (nothing) or mismatched codec lists, codec negotiation failed.

Solution:

; Add matching codec to both sides in sip-vicidial.conf
[6001]
allow=g711u
allow=g729

[carrier-x]
allow=g711u
allow=g729

Reload and retry:

asterisk -rx "sip reload"

Problem 2: Excessive CPU Usage During Calls

Symptom: CPU spikes when calls connect; agent reports call quality degradation.

Root cause: Unnecessary transcoding between codecs.

Diagnosis:

asterisk -rx "sip show channels" 

If call shows different codecs in "Recv" and "Send" formats (e.g., recv: opus, send: g711u), transcoding is active.

Solution: Align codec preference. If carrier only supports G.729 but agent uses Opus:

[6001]
; Prioritize G.729 to match carrier
disallow=all
allow=g729
allow=g711u
allow=opus

Or upgrade carrier to support Opus.

Problem 3: G.729 License Exhaustion

Symptom: G.729 calls fail midway or fail to connect; other codecs work.

Error in logs:

ERROR: g729 codec license limit exceeded

Diagnosis:

asterisk -rx "codec show"

Look for G.729 license count.

Solution:

Purchase additional licenses or switch to G.711 (uncompressed) or Opus (free).

; Temporary workaround: prioritize G.711
disallow=all
allow=g711u
allow=opus

Problem 4: Carrier Rejecting Codec Offer

Symptom: Calls to specific carrier fail with SIP 488 "Not Acceptable Here"

Diagnosis: Use ngrep to capture SDP offer:

sudo ngrep -W byline 'INVITE' 'host CARRIER_IP and port 5060'

Check what codecs you're offering vs. what carrier accepts.

Solution: Contact carrier for supported codec list and update peer configuration:

[carrier-problematic]
type=peer
host=sip.carrier.com
; Restrict to codecs carrier actually supports
disallow=all
allow=g711u
allow=g729

Problem 5: Codec Misalignment After Config Change

Symptom: Changed codec settings in config file but calls still use old codec.

Root cause: Asterisk daemon hasn't reloaded configuration.

Solution:

# Reload SIP module
asterisk -rx "sip reload"

# If that doesn't work, reload entire Asterisk
asterisk -rx "core reload"

# Verify change with specific peer
asterisk -rx "sip show peer carrier-a-main"

Performance Benchmarking

CPU Impact by Codec

Test transcoding load on your hardware. Create a test call and monitor:

# Terminal 1: Start monitoring
watch -n1 'asterisk -rx "core show threads" | head -20'

# Terminal 2: Run synthetic call load
for i in {1..10}; do
  asterisk -rx "channel originate SIP/6001 extension 1000@test-context"
done

Typical results on modern server (Intel Xeon 2.4 GHz):

Scenario CPU/call Calls/core
G.711 passthrough 0.5% 200
G.729 passthrough 1% 100
G.711↔G.729 transcode 3-5% 20-30
Opus↔G.729 transcode 4-6% 15-25

Bandwidth Impact

Monitor SIP trunk bandwidth:

# Install iftop
sudo apt-get install iftop

# Monitor specific interface
sudo iftop -i eth0 -nNP

# Or use vnstat for long-term stats
sudo vnstat -h -i eth0

Expected bandwidth per codec:

Codec Bitrate Per call (both directions)
G.711 64 kbps 128 kbps
G.729 8 kbps 16 kbps
Opus @ 24kbps 24 kbps 48 kbps

Production Checklist

Before deploying codec changes to production:

Summary

Codec negotiation in Asterisk/ViciDial is the intersection of quality, bandwidth, and processing power. The optimal choice depends on your specific constraints:

Choose G.711 if:

Choose G.729 if:

Choose Opus if:

In production ViciDial deployments:

  1. Define your constraint: bandwidth, CPU, or quality
  2. Map carrier capabilities: Know what each carrier supports
  3. Configure hierarchical preferences: Global defaults with peer overrides
  4. Monitor continuously: Track CPU, bandwidth, and MOS scores
  5. Test thoroughly: Lab validation before production rollout
  6. Document decisions: Record why each codec choice was made

The most common mistake is forcing a single codec globally when a multi-codec strategy (high-quality internal, optimized external) works better. Use codec negotiation as a tool to balance competing demands, not as a binary choice.

Need expert help with your setup?

VoIP infrastructure consulting, AI voice agent integration, monitoring stacks, scaling — I've done it all in production.

Get a Free Consultation