In many automation and telephony integration scenarios, developers need a lightweight way to initiate SIP calls and play audio files without GUI dependencies. This is particularly useful for:
- IVR system prototyping
- Automated notification systems
- Telephony integration in CI/CD pipelines
- Batch calling operations
Here are three practical approaches to achieve this functionality:
1. Using pjsua from PJPROJECT
The most robust solution is using pjsua
from the PJSIP library. Here's a sample bash script:
#!/bin/bash
PHONE_NUMBER=$1
AUDIO_FILE=$2
pjsua --id sip:user@your.sip.provider \
--registrar sip:your.sip.provider \
--username your_username \
--password your_password \
--realm '*' \
--auto-play \
--play-file=$AUDIO_FILE \
sip:$PHONE_NUMBER
2. Python with SIPPY
For more programmatic control:
from sippy.SipCall import SipCall
import time
def make_call(number, audio_file):
sip_acc = {
'sip_user': 'username',
'auth_user': 'authname',
'pwd': 'password',
'proxy': 'sip.provider.com'
}
call = SipCall(sip_acc)
call.default_timeout = 30
call.connect(number)
if call.connected:
call.play_wav(audio_file)
time.sleep(10) # Wait for playback
call.hangup()
make_call('+1234567890', 'message.wav')
3. Linphone Command Line
Linphone offers CLI capabilities with its linphonec
tool. First create a configuration file (~/.linphonerc
):
[sip]
sip_listen_port=5060
reg_proxy=sip:your.provider.com
reg_identity=sip:user@your.provider.com
reg_expires=3600
reg_password=yourpassword
Then create an expect script to automate the call:
#!/usr/bin/expect -f
set number [lindex $argv 0]
set audio [lindex $argv 1]
spawn linphonec
expect "linphonec> "
send "play $audio\n"
expect "linphonec> "
send "call $number\n"
expect "Call with .* established"
sleep 10
send "terminate\n"
expect "linphonec> "
send "quit\n"
When implementing SIP dialing, consider these aspects:
- Codec compatibility - Ensure your audio file matches supported codecs (PCMA/PCMU for G.711, GSM, etc.)
- Authentication - Some providers require specific auth methods
- DTMF support - If you need to send touch tones after connection
- Error handling - Network issues, busy signals, etc.
Here's how to implement a Python solution with async support using asyncio
and aiosip
:
import asyncio
import aiosip
from aiosip.media import RTPEndpoint, WavePlayer
async def make_call():
sip_config = {
'srv_host': 'sip.provider.com',
'srv_port': 5060,
'user': 'username',
'pwd': 'password'
}
peer = await aiosip.Peer.create(
local_addr=('0.0.0.0', 5060),
remote_addr=(sip_config['srv_host'], sip_config['srv_port'])
)
dialog = await peer.invite(
from_details=aiosip.Contact.from_header(f'sip:{sip_config["user"]}@{sip_config["srv_host"]}'),
to_details=aiosip.Contact.from_header('sip:+1234567890@sip.provider.com')
)
if dialog.state == 'connected':
rtp = RTPEndpoint(dialog)
player = WavePlayer('message.wav')
rtp.connect(player)
await asyncio.sleep(10) # Play duration
await dialog.bye()
peer.close()
asyncio.run(make_call())
For production systems:
- Use SRTP for secure media transmission
- Implement proper logging (SIP messages, call status)
- Add retry logic for transient failures
- Consider using a SIP ALG if behind NAT
When working with SIP telephony in Unix environments, we often encounter scenarios that demand automated calling capabilities - whether for notification systems, IVR testing, or batch call processing. The ideal solution should combine SIP connectivity with media playback in a lightweight command-line package.
After extensive testing, these CLI tools stand out for SIP calling with media support:
1. pjsua - Comes with PJSUA CLI interface
2. sipcmd - Lightweight SIP command line tool
3. linphonec - Console version of Linphone
4. baresip - Modular SIP client with CLI
The sipcmd
utility provides the most straightforward approach for our use case. Here's how to install and use it:
# Installation on Debian/Ubuntu
sudo apt install sipcmd
# Basic call with audio playback
sipcmd -u username -p password -P sip.provider.com \
-c "dtmf 1234; play /path/to/message.wav; wait 20; hangup" \
-w -x "c 18005551234"
For more complex scenarios, we can create scriptable solutions:
#!/bin/bash
PHONE="+18005551234"
AUDIO_FILE="/opt/ivr/greeting.wav"
SIP_SERVER="sip.example.com"
SIP_USER="1001"
SIP_PASS="secret"
sipcmd -u $SIP_USER -p $SIP_PASS -P $SIP_SERVER \
-c "play $AUDIO_FILE; wait 30; hangup" \
-w -x "c $PHONE"
For more programmatic control, PJSUA offers Python integration:
import pjsua
lib = pjsua.Lib()
lib.init()
lib.start()
acc = lib.create_account(pjsua.AccountConfig(
"sip.provider.com", "username", "password"))
call = acc.make_call("sip:18005551234@sip.provider.com",
cb=MyCallCallback())
# In callback class:
def on_media_state(self):
if self.lib.media_active:
player = self.lib.create_player("message.wav")
self.lib.connect_player_to_call(player, self.call)
- Codec mismatches - Ensure your SIP server and client support compatible codecs (PCMA/PCMU for WAV files)
- Firewall settings - SIP uses 5060 UDP/TCP by default
- Audio file format - Convert to 8kHz/16bit mono WAV for best compatibility
When processing large call volumes:
- Use ulimit to increase file descriptors
- Consider separate processes for concurrent calls
- Monitor CPU usage with top/htop during calls