This directory contains a standalone, API-driven VoIP calling agent container built on top of PJSIP (PJSUA2) and FastAPI in Python. It is optimized to run inside headless environments (like Docker containers or remote servers) without physical audio hardware.
For a detailed step-by-step walkthrough of how this PJSIP container is compiled and built, see README_BUILD.md.
x86_64 and arm64/Apple Silicon).audDevManager().setNullDev() to prevent PJMEDIA_EAUD_NODEFDEV (Unable to find default audio device) crashes common in server environments.PYTHONUNBUFFERED=1 to ensure PJSIP signaling and Python print logs are shown immediately in Docker outputs.Navigate to this directory (or run from the project root referencing this folder) and build the image:
docker build -t pjsua2-call-agent .
(Note: Compiling PJSIP from source will take 3-7 minutes during the initial build.)
Start the container exposing the FastAPI server on port 8000. To play local audio files, map a folder containing your .wav files into the container:
docker run -d --name voip-agent -p 8000:8000 -v ./sounds:/app/sounds pjsua2-call-agent
To initiate a SIP call, send an HTTP POST request to /api/call. The call runs synchronously and returns the final call outcome in the API response after the call ends.
You can place any audio file (e.g., .mp3, .wav) in the sounds/ directory. The container will automatically standardize it to the compliant format (PCM 16-bit, 8000Hz, Mono WAV) using FFmpeg before making the call:
curl -X POST http://localhost:8000/api/call \
-H "Content-Type: application/json" \
-d '{
"target_uri": "sip:[email protected]",
"caller_id": "CustomAgent",
"media_file_name": "announcement.mp3"
}'
If you send raw text, the container will synthesize it into natural Turkish speech using Piper TTS (Fahrettin voice) and automatically append the official voice prompt: "Alarmı tekrar dinlemek için 1'e, çağrıyı sonlandırmak için 0'a basın."
curl -X POST http://localhost:8000/api/call \
-H "Content-Type: application/json" \
-d '{
"target_uri": "sip:[email protected]",
"caller_id": "CustomAgent",
"text": "Merhaba İlker Bey, sisteminizde kritik bir durum tespit edildi."
}'
The call executes and blocks the HTTP request until it finishes. There are the following possible outcomes returned in the API response under "result":
"0 a basıldı": The recipient pressed 0 to end the call. (Returns immediately)"kullanıcı tarafından kapatıldı": The recipient hung up the phone without pressing 0. (Returns immediately)"1 e basıldı": The recipient pressed 1 at least once to replay the message (and did not end with 0). (Returns immediately)"break infinite loop": The recipient listened to the message but did not press 1 or 0. To prevent infinite looping, the container played the recording 3 times maximum and hung up. (Returns immediately)"cevap vermedi veya meşgul": The recipient did not pick up the call within 45 seconds or was busy. (Retries once after waiting 60 seconds)"error": A network, SIP, or media configuration error occurred. (Retries once after waiting 60 seconds){
"status": "completed",
"target": "sip:[email protected]",
"result": "break infinite loop"
}
To watch the call progression (INVITE, ringing, answer, duration, disconnect codes):
docker logs -f voip-agent
To tag and upload this image to your Docker Hub repository:
docker login
docker tag pjsua2-call-agent your-username/pjsua2-call-agent:latest
docker push your-username/pjsua2-call-agent:latest
Content type
Image
Digest
sha256:03ed31ce5…
Size
249.9 MB
Last updated
3 months ago
docker pull imansur/pjsua2-call-agent