Python SIP Library for Custom VoIP Solutions
PySIP is an asynchronous Python library designed to simplify working with the Session Initiation Protocol (SIP) for VoIP communication. Whether you're building automated call systems, interactive voice response (IVR) menus, or any SIP-based application, PySIP gives you the flexibility to create and manage SIP accounts, handle calls, and implement custom logic with ease.
Feature | Description |
---|---|
Complete SIP Account Management | Easily create, register, and manage SIP accounts. |
Custom Call Flows | Write scripts to automate call flows with your own business logic. |
UDP Transport Layer | Asynchronous, efficient UDP transport for sending and receiving SIP messages. |
Flexible Call Handling | Handle incoming and outgoing SIP calls, play messages, and gather user input. |
Fully Extensible | Includes an example bot for appointment booking, but you can easily write any SIP-based automation you need. |
- Installation
- Project Structure
- Getting Started
- Detailed Usage
- Example Script
- Creating Your Custom SIP Scripts
- Contributing
You can install PySIP directly from PyPI using pip:
pip install PySIPio
Caution
Note that the package name on PyPI is PySIPio
and not PySIP
git clone https://github.com/moha-abdi/PySIP.git
cd PySIP
Ensure you have Python 3.8+ installed. Install the required dependencies using:
pip install -r requirements.txt
The project is structured to provide a clean separation between the core SIP library and any custom scripts you want to write. Here's an overview of the project layout:
PySIP/
│
├── PySIP/ # Core library files
│ ├── sip_account.py # SIP account management
│ ├── sip_core.py # SIP message parsing and handling
│ ├── udp_handler.py # Asynchronous UDP transport for SIP
│
├── scripts/ # Example custom scripts
│ └── appointment_booking_bot.py # Example bot for appointment booking
│
├── test.py # Example usage of PySIP for testing
├── requirements.txt # Project dependencies
├── .env.example # Example environment configuration
└── README.md # Project documentation
Create a .env
file in your working directory to store your SIP account credentials and server details:
SIP_USERNAME=your_sip_username
SIP_PASSWORD=your_sip_password
SIP_SERVER=your_sip_server
A SIP account is essential for handling calls. To start, you need to create an instance of the SipAccount
class, which requires your SIP credentials (username, password, and server). Here's how to do it:
from PySIP.sip_account import SipAccount
import os
from dotenv import load_dotenv
# Load SIP credentials from .env file
load_dotenv()
account = SipAccount(
os.environ["SIP_USERNAME"],
os.environ["SIP_PASSWORD"],
os.environ["SIP_SERVER"],
)
Once the SipAccount
is created, the next step is to register it with the SIP server:
await account.register()
This sends a SIP REGISTER
request to the server to activate the account. Once registered, you can make calls or listen for incoming calls.
The SipAccount
class is at the core of PySIP. It handles all account-related tasks such as registration, making calls, and unregistering from the SIP server.
account = SipAccount(username, password, server)
Call the register()
method to register the SIP account with the server:
await account.register()
The make_call(destination)
method initiates a call to the destination number:
call = account.make_call("destination_number")
Use the on_incoming_call
decorator to define a function that will handle incoming calls:
@account.on_incoming_call
async def handle_incoming_call(call: SipCall):
await call.accept() # or call.reject() or call.busy()
await call.call_handler.say("Thank you for calling us!")
await call.call_handler.hangup()
When you're done, unregister the account to gracefully close the session:
await account.unregister()
The CallHandler
is responsible for handling the call flow. It allows you to say messages, gather input from the caller, or transfer the call.
await call_handler.say("Welcome to our service.")
Use gather()
to gather input from the user, such as pressing a digit:
dtmf_key = await call_handler.gather(length=1, timeout=5)
You can forward the call to another number:
await call_handler.transfer_to("1234567890")
For incoming calls, you can use the following methods:
await call.accept() # Accept the incoming call
await call.reject() # Reject the incoming call
await call.busy() # Mark the line as busy for the incoming call
The UdpHandler
is an internal module that manages the asynchronous sending and receiving of SIP messages over the network.
The send_message()
method sends a UDP message to the SIP server or peer:
self.transport.sendto(message)
The datagram_received()
method handles incoming messages, placing them in a queue for processing:
self.data_q.put_nowait(data)
To demonstrate PySIP in action, we've provided a basic example of an appointment booking bot. This bot allows callers to book appointments via a phone call.
import asyncio
from PySIP.sip_account import SipAccount
from scripts.appointment_booking_bot import appointment_booking_bot
from dotenv import load_dotenv
import os
# Load environment variables
load_dotenv()
# Initialize SIP account with credentials from .env file
account = SipAccount(
os.environ["SIP_USERNAME"],
os.environ["SIP_PASSWORD"],
os.environ["SIP_SERVER"],
)
@account.on_incoming_call
async def handle_incoming_call(call: SipCall):
await call.accept()
await call.call_handler.say("We have received your call successfully")
async def main():
# Register the SIP account
await account.register()
# Make a call to a test number (e.g., '111')
call = account.make_call("111")
call_task = asyncio.create_task(call.start())
# Run the appointment booking bot
await appointment_booking_bot(call.call_handler, customer_name="John")
# Wait for the call to complete, then unregister
await call_task
await account.unregister()
if __name__ == "__main__":
asyncio.run(main())
While the appointment booking bot is just one example, PySIP is designed to let you create any SIP-based automation or custom script that fits your needs.
To create your own script:
- Create a Python file in the
scripts/
directory. - Write your custom call logic using the
CallHandler
class to control the call flow. - Use the
SipAccount
to register and make calls as demonstrated in the example script.
Contributions are welcome! If you would like to contribute to the development of PySIP, feel free to open issues or submit pull requests.
Made with ❤️ by Moha Abdi