Repository navigation
v0.1.0 — Within Earshot (first public release)
mod_earshot 0.1.0 — first public release
A FreeSWITCH module that bridges live call audio to your AI voice agent over one WebSocket — full-duplex, with the agent's voice played back reliably on the same leg. A drop-in mod_audio_stream alternative whose playback actually works, with seven protocol adapters, module-side turn-taking, agent-driven call control, PCI masking, multi-stream fan-out, and typed ESL events.
The transport, full-duplex audio path, and playout are validated end-to-end on real SIP calls with real audio — live OpenAI Realtime and Deepgram Voice Agent sessions (Deepgram from a hardware SIP phone), plus a shared-pool concurrency + soak load test.
Highlights
- Playback that works — the
WRITE_REPLACEagent→caller path validated with real audio, full duplex, on one leg. This is the wedge the incumbent module never delivered. - 7 protocol adapters —
native,twilio,openai(Realtime),deepgram(Voice Agent),elevenlabs,gemini(Live),pipecat. Swap vendors with one word (proto=). - Turn-taking for any agent — module-side VAD →
speech_started/speech_stopped, a ready-gate (no "answered into silence"), and speech-triggered barge-in. - Agent drives the call — opt-in, whitelisted control channel (transfer / hangup / DTMF / play / record / hold / bridge / setvar), every action audited via
earshot::command. - PCI/PII masking — mute caller audio + redact DTMF to the agent during card entry, while digits still reach a secure collector.
- Multi-stream fan-out — agent + live transcription + supervisor on one call.
- Scales with sessions, not threads — all streams share a small pool of libwebsockets service contexts (~1 MB/session vs ~17 MB thread-per-stream), so a small box holds thousands of sessions where thread-per-stream hit a wall near ~420. Validated to 150 concurrent + a 12-minute flat-memory soak, mass-teardown/RST-storm without a crash, and a ThreadSanitizer-clean fuzz run.
- Observable — typed
earshot::custom events over the FreeSWITCH event socket (ESL) + latency KPIs (time-to-first-audio, per-turn response, WebSocket RTT), keyed to a two-key trace (SIP Call-ID + channel UUID). - Drop-in migration —
uuid_audio_stream/audio_streamcompat runs existingmod_audio_streamdialplans unchanged.
Adapter validation (stated per vendor, not blanket)
native · openai · deepgram — live-validated on a real call · pipecat — against Pipecat's official protobuf schema · twilio — WebSocket echo round-trip · elevenlabs · gemini — implemented, not yet live-validated (see the adapter status table in the README).
Install
Needs FreeSWITCH dev headers + libwebsockets-dev:
cmake -S . -B build && cmake --build build
sudo cmake --install build # -> /usr/lib/freeswitch/mod/mod_earshot.so
fs_cli -x "load mod_earshot"
Quickstart recipes in QUICKSTART.md, full option/verb/event reference in docs/API.md.
License: MIT · Full changelog: CHANGELOG.md