Skip to content

Blog

Sipral 1.2: voice agents, more platforms, and a week of calls

· Sipral

Sipral 1.2 is out, eleven days after 1.1. It was planned for November, and a second release, 1.3, was planned for next year; everything both promised is done, so it ships as one.

Voice agents

A voice agent answers the phone the way a person does: on an extension of the company’s PBX. 1.2 brings the pieces between the two:

  • a SIP bridge from a PBX line to any voice agent that answers SIP, with digits, transfers and the outcome handed back to the PBX;
  • a transport for Pipecat, and direct connectors to the realtime speech APIs of five services;
  • a bridge run from one configuration file, each account to its own agent;
  • a phone voice agent that runs on one machine, speech to speech, with no API key;
  • answering-machine detection on the calls an agent places: hang up, leave a message at the beep, or connect anyway.

The first audio frame reaches the agent 31.5 ms after the INVITE arrives, and the agent’s reply is on the wire 20.4 ms after it writes it: medians of 300 calls through the lab’s Asterisk.

More platforms, and the enterprise

  • Node.js and TypeScript, and .NET MAUI for iOS and Android, beside the Swift, Kotlin and Java, .NET, Python, Dart and React Native packages. Eight languages over one C interface.
  • The .NET packages now carry Windows on ARM, as the Python wheels already did.
  • OAuth2 sign-in to the PBX (RFC 8898), SIP over a WebSocket the stack opens itself (RFC 7118), LiveCommunicationKit on iOS 17.4 and later, and a network test before the call that answers in one word: good, acceptable or poor.

An application built on 1.0 or 1.1 works with 1.2 unchanged: the C interface only grew.

Rust, with a promise

Until now the Rust crates carried no promise between releases: the C interface and the language packages did. From 1.2 the sipral crate on crates.io promises the same: a program that builds against 1.2 builds against every later 1.x. Every type it hands over has a name a program can write, every type that may grow is marked so it can grow without breaking anyone, and the gate checks each change against the last release with cargo-semver-checks.

Proven against more of what is deployed

Since 1.1 the lab has added FusionPBX, a live VitalPBX, where it found a callee who heard nothing and the fix, and a VICIdial dialer, where an agent’s phone is rung into its session and joined to a caller. Sipral was measured against PJSIP, baresip and Linphone on one Asterisk, three hours side by side, with the least memory and processor time of the four (the comparison).

A week of calls

For seven days, from 7 to 14 October, the headless agent took one three-minute call after another from Asterisk and registered again every minute or two: 3,337 calls and 6,795 registrations, no error. It used 2.2 % of one core on average, the same on the seventh day as on the first. Resident memory reached 6.02 MB in its first day and ended the week at 6.07 MB; a counting test of the same work holds the library itself flat to 35,000 calls. The figures are in the numbers chapter.

Install

pip install sipral                # or sipral-opus
dotnet add package Sipral         # Sipral.Opus, Sipral.Maui
npm install sipral                # sipral-react-native for React Native
cargo add sipral
dart pub add sipral

On Android and the JVM, org.sipral:sipral and org.sipral:sipral-jvm from Maven Central; for Swift, this package: https://github.com/SIPRAL/sipral, from 1.2.0. What changed, line by line, is in the changelog.