Documentation |
Issues |
Changelog |
Funding ♥
Python VoIP
Async VoIP Python library for the AI age.
Sponsors
Usage
To get started, you will need a SIP account. One is usually included with ISP. Check your ISP's documentation or router for details.
You will need a SIP AOR (URI), which looks like this:
sip:USER:PASSWORD@SIP_SERVER
CLI
A simple echo call can be started with:
uvx 'voip[cli]' sip sip:alice:********@sip.example.com echo
Each command supports an optional --dial argument to initiate an
outbound call instead of waiting for an inbound one.
To dial a number, say a message, and hang up automatically:
uvx 'voip[cli]' sip sip:alice:********@sip.example.com say sip:+15551234567@sip.example.com "Your package has arrived."
You can also talk to a local agent (needs Ollama):
uvx 'voip[cli]' sip sip:alice:********@sip.example.com agent --initial-prompt "Hi, I am looking for a Mr. Ron, first name Mo?"
MCP
The voip package ships a ready-made Model Context Protocol (MCP) server
that exposes tools to make phone calls on your behalf to any MCP client.
{
"mcpServers": {
"VoIP": {
"type": "stdio",
"command": "uvx",
"args": [
"voip[mcp]",
"mcp"
],
"env": {
"SIP_AOR": "sip:number:password@example.com"
}
}
}
}
Python API
uv add voip[audio,ai,pygments]
Subclass TranscribeCall and override transcription_received to handle results.
Pass it as session_class when answering an incoming call:
import asyncio
import dataclasses
from voip.ai import TranscribeCall
from voip.sip.protocol import SIP
from voip.sip.types import SipURI
from voip.sip.transactions import InviteTransaction
from voip.rtp import RealtimeTransportProtocol
from faster_whisper import WhisperModel
@dataclasses.dataclass(kw_only=True, slots=True)
class TranscribingCall(TranscribeCall):
def transcription_received(self, text) -> None:
print(text)
class TranscribeInviteTransaction(InviteTransaction):
def invite_received(self, request) -> None:
self.ringing()
self.answer(
session_class=TranscribingCall,
stt_model=WhisperModel("kyutai/stt-1b-en_fr-trfs", device="cuda"),
)
async def main():
loop = asyncio.get_running_loop()
_, rtp_protocol = await loop.create_datagram_endpoint(
RealtimeTransportProtocol,
local_addr=("0.0.0.0", 0),
)
await loop.create_connection(
lambda: SIP(
rtp=rtp_protocol,
aor=SipURI.parse("sip:alice:********@example.com"),
transaction_class=TranscribeInviteTransaction,
),
host="sip.example.com",
port=5060,
)
await asyncio.Future()
asyncio.run(main())
For raw audio access without transcription, subclass AudioCall and override
audio_received(self, audio: np.ndarray) instead.
Metadata
Release files for VoIP 0.6.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| voip-0.6.0.tar.gz | 75.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| voip-0.6.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 164.3 kB
Release files / voip-0.6.0.tar.gz
| Download URL | voip-0.6.0.tar.gz |
|---|---|
| Size | 75.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
32006d7e270d812de9fc2e5f71cb292e77d00dd4d5bd272052c20fbacd238f00
|
|
BLAKE2b-256 checksum How to use checksums |
2f0b87537a16ca70849c4fdf217c826421016a6f408299a381dcd49781881a28
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 10, 2026.
Transparency logRelease files / voip-0.6.0-py3-none-any.whl
| Download URL | voip-0.6.0-py3-none-any.whl |
|---|---|
| Size | 88.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
189df4a0ef63ce2e2f5a02aa3b19d73857e1f34cb713bc2b8fd1f57f19b471cb
|
|
BLAKE2b-256 checksum How to use checksums |
26f7fd261819515fea72752781dc16896a775284a0a3c2b0b3165454306483e0
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 10, 2026.
Transparency log