A lightweight Python-based SIP client with voice support
Project description
uSIP - Lightweight Python SIP Client
A lightweight Python-based SIP client with full voice support, designed for professional VoIP applications.
Features
- ๐ฏ Full SIP Protocol Support: Registration, calls, messaging, presence
- ๐ Voice Communication: Real-time audio streaming with RTP
- ๐ง Audio Device Management: List, select, and switch audio devices dynamically
- ๐ฑ Event-Driven Architecture: Comprehensive callback system for all SIP events
- ๐ Call Management: Multiple concurrent calls, call history, statistics
- ๐๏ธ Flexible Audio: Runtime device switching, audio preferences
- ๐ Automatic Session Management: Keep-alive, re-registration, session refresh
Installation
From PyPI (Recommended)
pip install uSIP
From Source
git clone https://github.com/Dashhhhhhhh/uSIP.git
cd uSIP
pip install -e .
Development Installation
git clone https://github.com/Dashhhhhhhh/uSIP.git
cd uSIP
pip install -e ".[dev]"
Requirements
- Python 3.8+
- PyAudio (for audio functionality)
- python-dotenv (for configuration)
- rich (for enhanced console output)
System Dependencies
Ubuntu/Debian
sudo apt-get install portaudio19-dev
macOS
brew install portaudio
Windows
PyAudio wheels are available for Windows, no additional setup required.
Quick Start
Basic Usage
from sip_client import SIPClient, SIPAccount
# Create SIP account
account = SIPAccount(
username="your_username",
password="your_password",
domain="your_sip_provider.com"
)
# Create and start client
client = SIPClient(account)
client.start()
# Register with server
client.register()
# Make a call
call_id = client.make_call("1234567890")
# Clean up
client.stop()
Using Environment Variables
Create a .env file:
SIP_USERNAME=your_username
SIP_PASSWORD=your_password
SIP_DOMAIN=your_sip_provider.com
SIP_PORT=5060
from sip_client import SIPClient
# Client will automatically load from environment
client = SIPClient()
client.start()
client.register()
Event Handling
from sip_client import SIPClient, CallState, RegistrationState
client = SIPClient()
# Set up event callbacks
def on_registration_state(state: RegistrationState):
print(f"Registration: {state.value}")
def on_incoming_call(call_info):
print(f"Incoming call from {call_info.remote_uri}")
client.answer_call(call_info.call_id)
def on_call_state(call_info):
print(f"Call {call_info.call_id}: {call_info.state.value}")
# Register callbacks
client.on_registration_state = on_registration_state
client.on_incoming_call = on_incoming_call
client.on_call_state = on_call_state
client.start()
client.register()
API Reference
SIPClient
The main client class providing all SIP functionality.
Core Methods
start()- Start the SIP clientstop()- Stop the client and clean up resourcesregister()- Register with SIP serverunregister()- Unregister from SIP server
Call Management
make_call(target_uri, input_device=None, output_device=None)- Make outgoing callanswer_call(call_id, input_device=None, output_device=None)- Answer incoming callhangup(call_id)- End a callget_calls()- Get list of active callsget_call(call_id)- Get specific call information
Audio Management
get_audio_devices()- List available audio devicesswitch_audio_device(call_id, input_device=None, output_device=None)- Switch devices during call
Event Callbacks
on_registration_state- Registration state changeson_incoming_call- Incoming call notificationson_call_state- Call state changeson_call_media- Media eventson_message- SIP message events
Data Models
SIPAccount
@dataclass
class SIPAccount:
username: str
password: str
domain: str
port: int = 5060
display_name: Optional[str] = None
CallInfo
@dataclass
class CallInfo:
call_id: str
local_uri: str
remote_uri: str
state: CallState
direction: str # "incoming" or "outgoing"
start_time: Optional[float] = None
answer_time: Optional[float] = None
end_time: Optional[float] = None
@property
def duration(self) -> float:
# Returns call duration in seconds
AudioDevice
@dataclass
class AudioDevice:
index: int
name: str
max_input_channels: int
max_output_channels: int
default_sample_rate: float
@property
def is_input(self) -> bool
@property
def is_output(self) -> bool
Enums
CallState
IDLE- No active callCALLING- Outgoing call initiatedRINGING- Call is ringingCONNECTED- Call is activeDISCONNECTED- Call ended normallyBUSY- Remote party is busyFAILED- Call failed
RegistrationState
UNREGISTERED- Not registeredREGISTERING- Registration in progressREGISTERED- Successfully registeredFAILED- Registration failed
Examples
Basic Call Example
from sip_client import SIPClient, SIPAccount, CallState
account = SIPAccount(
username="user",
password="pass",
domain="provider.com"
)
client = SIPClient(account)
client.start()
client.register()
# Make a call
call_id = client.make_call("1234567890")
# Wait for call to connect
import time
time.sleep(5)
# Check call status
call = client.get_call(call_id)
if call and call.state == CallState.CONNECTED:
print(f"Call connected! Duration: {call.duration:.2f}s")
# End call after 10 seconds
time.sleep(10)
client.hangup(call_id)
client.stop()
Audio Device Management
from sip_client import SIPClient
client = SIPClient()
client.start()
# List available audio devices
devices = client.get_audio_devices()
for device in devices:
print(f"{device.index}: {device.name} ({'INPUT' if device.is_input else ''} {'OUTPUT' if device.is_output else ''})")
# Make call with specific devices
call_id = client.make_call("1234567890", input_device=1, output_device=2)
# Switch devices during call
client.switch_audio_device(call_id, input_device=3, output_device=4)
client.stop()
Multiple Concurrent Calls
from sip_client import SIPClient
client = SIPClient()
client.start()
client.register()
# Make multiple calls
call1 = client.make_call("1234567890")
call2 = client.make_call("0987654321")
# Manage calls independently
calls = client.get_calls()
for call in calls:
print(f"Call {call.call_id}: {call.remote_uri} ({call.state.value})")
# End specific call
client.hangup(call1)
client.stop()
Architecture
The library follows a modular architecture:
sip_client/
โโโ __init__.py # Public API
โโโ client.py # Main SIP client
โโโ models/ # Data models
โ โโโ account.py # SIP account
โ โโโ call.py # Call information
โ โโโ enums.py # State enumerations
โโโ audio/ # Audio management
โ โโโ manager.py # Audio streaming
โ โโโ devices.py # Device management
โโโ sip/ # SIP protocol
โ โโโ protocol.py # Core protocol
โ โโโ messages.py # Message handling
โ โโโ authentication.py # Authentication
โโโ utils/ # Utilities
โโโ helpers.py # Helper functions
Testing
Run the test suite:
# Run all tests
pytest
# Run with coverage
pytest --cov=sip_client
# Run specific test categories
pytest -m unit # Unit tests only
pytest -m integration # Integration tests only
pytest -m "not audio" # Skip audio tests
Development
Setting up Development Environment
git clone https://github.com/Dashhhhhhhh/uSIP.git
cd uSIP
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
pip install -e ".[dev]"
Code Quality
# Format code
black src tests examples
# Sort imports
isort src tests examples
# Type checking
mypy src
# Linting
flake8 src tests examples
# Run all quality checks
pre-commit run --all-files
Running Examples
# Basic usage
python examples/basic_usage.py
# Advanced features
python examples/advanced_usage.py
Performance
- Memory Usage: ~10MB baseline, ~5MB per active call
- CPU Usage: <5% during calls on modern hardware
- Latency: <50ms audio latency with proper audio device configuration
- Concurrent Calls: Supports 50+ concurrent calls (limited by system resources)
Troubleshooting
Common Issues
-
PyAudio Installation Problems
# Ubuntu/Debian sudo apt-get install portaudio19-dev pip install pyaudio # macOS brew install portaudio pip install pyaudio
-
Audio Device Issues
# List available devices devices = client.get_audio_devices() for device in devices: print(f"{device.index}: {device.name}")
-
Registration Issues
- Check SIP credentials
- Verify network connectivity
- Ensure SIP server is accessible
- Check firewall settings (UDP port 5060)
-
Call Issues
- Verify registration status
- Check audio device availability
- Ensure RTP ports are not blocked (UDP 10000+)
Debug Logging
import logging
logging.basicConfig(level=logging.DEBUG)
# Enable SIP message logging
client = SIPClient()
client.on_message = lambda msg, addr: print(f"SIP: {msg}")
Contributing
We welcome contributions! Please see CONTRIBUTING.md for details.
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests
- Submit a pull request
License
This project is licensed under the MIT License - see the LICENSE file for details.
Acknowledgments
- Built on top of the Session Initiation Protocol (RFC 3261)
- Audio functionality powered by PyAudio
- Inspired by PJSIP and other professional SIP libraries
- Thanks to all contributors and testers
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file usip-1.0.0.tar.gz.
File metadata
- Download URL: usip-1.0.0.tar.gz
- Upload date:
- Size: 34.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.11.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9ca498c0f99a667c4593bf24b4a7e8f2696824222c1b8b9395fc073f056f534f
|
|
| MD5 |
7d6bf7a1cfc90fcc50d8d727abb0b031
|
|
| BLAKE2b-256 |
09d09497959b692869f2a82c42855a462727ce1dacf39f73dc05d48cbcc426be
|
File details
Details for the file usip-1.0.0-py3-none-any.whl.
File metadata
- Download URL: usip-1.0.0-py3-none-any.whl
- Upload date:
- Size: 36.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.11.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c9281b77f4d1aa1f412e1aea5654e08f9c1993559c2e560fb3eaa16f04335e57
|
|
| MD5 |
25d08dc4e5fd8aa29c548d323131deba
|
|
| BLAKE2b-256 |
8fe7ec7584990e18726cb5723fe27c1082fcc9a876154cf5010324a42d9f53b3
|