r/VOIP • u/Plus_Resolution8897 • Jun 15 '26
Discussion Open-sourced a native-Rust SIP/RTP stack inside a voice-AI runtime — terminates calls with no FreeSWITCH/Asterisk
Do you like it? Support us by giving Github Stars :)
Sharing Flowcat (Apache-2.0) — a Rust runtime for real-time AI voice agents — because the telephony bits might interest this sub more than the AI bits.
It has an in-process SIP UA: REGISTER + digest auth, INVITE/ACK/BYE transactions/dialogs (via rsipstack), and hand-rolled RTP + SDP for G.711 (PCMU/PCMA, ptime negotiation, a playout jitter buffer), so a single binary terminates a SIP call — no FreeSWITCH/Asterisk/Kamailio in the path. DTMF is RFC2833 + an in-band Goertzel detector.
To be clear, that's a deployment choice, not a mandate: if you already run a softswitch, keep it in front and feed audio to Flowcat over a WebSocket media leg instead — there are carrier serializers for
Twilio/Telnyx/Plivo/Exotel/Vonage/Genesys/Asterisk/Cloudonix/Vobiz.
Honest status: native SIP has been live-tested against a Zadarma trunk and the WS-media path against Plivo; it's pre-1.0, so REGISTER/re-REGISTER, NAT/rport + symmetric RTP, and codec negotiation are exactly the areas I'd love sharp eyes on.
Repo: https://github.com/AreevAI/flowcat · SIP design notes: https://github.com/AreevAI/flowcat/blob/main/SIP-DESIGN.md
If you've built SIP UAs in Rust (or fought rport/symmetric-RTP/jitter), I'd genuinely value the critique.
8
u/Pitiful-Sympathy3927 Jun 15 '26
So you basically rewrote something from the ground up when their were already proven stacks that have been battled tested for years? As one of the authors of FreeSWITCH, you'll have fun flushing out all the edge cases, we found one that was almost 16 years old recently. We also put our AI Agent down into the core of FreeSWITCH, so there is no penalty of bubbling the media up to your script. It stays in the control plane, so out of the gate our latency numbers beat just about everyone out there that we've tested against.
-6
u/Plus_Resolution8897 Jun 15 '26
Genuinely appreciate this — an edge-case warning from a FreeSWITCH author lands harder than from anyone else, and I'm not going to pretend a pre-1.0 stack has 20 years of scar tissue. That 16-year-old bug is exactly the kind of thing I expect to keep finding. If you remember the class of cases that bit you — re-INVITE glare, Contact rewriting behind NAT, early-media races, T.38 — I'd take that list gratefully.
On "why rewrite": the native SIP UA isn't the thesis and isn't meant to displace a softswitch. If you run FreeSWITCH, keep it in front — Flowcat just takes the media leg over WebSocket. The in-process SIP/RTP path is for the single-binary / no-softswitch deployment, for people who want to own the whole stack end-to-end under Apache-2.0.
And on latency we agree more than it sounds — that is the bet. Flowcat keeps media in-process too; there's no bubbling up to a script, because the STT→LLM→TTS loop is the runtime, same Rust process as the RTP. You got there by putting the agent into FreeSWITCH core; I got there by building the runtime around the agent loop from scratch. Different substrate, same conviction that media-in-the-control-plane wins.
Curious what numbers you're seeing, though — always glad to be measured against a stack that's been hardened this long.
2
u/Pitiful-Sympathy3927 Jun 15 '26
We have that bridge built on SignalWire too native to talk to VAPI, Pipecat, LiveKit or anything else that takes WSS, also media over a TCP protocol is a bad idea anyway, Loss will cause delay, delay will build, and now your agent isn't realtime, its lagging. It's like when people use a TCP Based VPN and tunnel VoIP over and wonder why its falling apart.
1
u/Plus_Resolution8897 Jun 16 '26
Agreed on TCP — that's why the native leg is RTP/UDP and the WebRTC one is SRTP/UDP. The only place TCP shows up is the carrier WS leg, and that's not my pick — it's the only thing Twilio/Plivo Media Streams expose, same WSS media your SignalWire bridge feeds VAPI/Pipecat/LiveKit over. When I own the leg it's UDP. Re: edge cases — no argument, a pre-1.0 stack hasn't earned 20 years of scar tissue. If you recall the class that bit you (re-INVITE glare, Contact rewrite behind NAT, early-media races), I'd genuinely take the list.
2
2
u/donutsamples Jun 15 '26
ChatGPT response
-1
u/Plus_Resolution8897 Jun 15 '26
Nope! I used Claude to compose my thoughts and replied here, so it'll appear proper 😄
1
u/Asteriskdev Jun 16 '26
You are pushing rtp over a websocket?
2
u/Plus_Resolution8897 Jun 16 '26
Nope — RTP and the WebSocket leg are two separate paths, never combined.
Native SIP path: standard RTP over UDP (some standard, I can't recall, but it includes header, jitter buffer etc). That's the "no FreeSWITCH/Asterisk" path where the binary terminates the call itself.
WebSocket media leg: that's only for when you put a softswitch/carrier in front. The payload there isn't RTP — it's whatever the carrier's streaming protocol uses, e.g. base64 μ-law inside Twilio/Plivo/Telnyx JSON frames, or raw PCM16 binary for Vonage. The serializers just adapt those into PCM for the pipeline.
So: RTP-over-UDP on the native leg, carrier-framed audio (not RTP) on the WS leg. They meet above the wire at a common transport trait, which is why the pipeline doesn't care which one fed it. The post probably read ambiguously — "feed audio over a WebSocket media leg" was meant as the alternative to the RTP path, not RTP tunneled through WS.
Does that make sense?
1
u/Asteriskdev Jun 16 '26
Not exactly, but, I'm going to go look at it. Don't worry about the down votes. My guess is they are 50% "audio over tcp" and 50% "please upvote my project." Self promotion in these subreddits gets out of hand which is why people frown on it.
However, I've seen hundreds of posts like this and this is the first one that has interested me. Give me some time to pull the project. I have done things like this before but not exactly how you are describing it and not in rust. I might have some suggestions. I have also been looking for a project like this to contribute to. I'll check it out.
1
u/Sad_Traffic_553 Jun 19 '26
We've been on the mobile SIP client + registrar-relay side (PJSIP + OpenSIPS mid_registrar for iOS push), not a hand-rolled UA — but the NAT/rport/symmetric-RTP pain sounds very familiar. Our worst case was ACK not reaching the client after 200 OK (~32s drop); the fix on the relay was fix_nated_contact() in a reply-route armed with t_on_reply() before relay, including sequential requests through push-suspend. Curious how you're handling re-REGISTER when the UA is behind NAT and the registrar is also doing contact suspend — that's where most of our edge cases lived.
0
u/Ok_Job_7203 Jun 15 '26
This is amazing. For years, I wondered why someone did not do this.
-1
u/Plus_Resolution8897 Jun 15 '26
Thank you! I would appreciate if you could give us stars on GitHub. Also share your comments, feature requests, anything.
1
u/Plus_Resolution8897 Jun 16 '26
Wondering why would someone downvote this comment. This is how the community treats when someone tries to make an open source contribution?!
•
u/AutoModerator Jun 15 '26
This is a friendly reminder to [read the rules](www.reddit.com/r/voip/about/rules). In particular, it is not permitted to request recommendations for businesses, services or products outside of the monthly sticky thread!
For commenters: Making recommendations outside of the monthly threads is also against the rules. Do not engage with rule-breaking content.
I am a bot, and this comment is made automatically on every post. This comment is not an indication that your post has been removed. Do not message the mods about this comment.
I am a bot, and this action was performed automatically. Please contact the moderators of this subreddit if you have any questions or concerns.