Voice abstraction layer for AgentPlexus supporting TTS, STT, and Voice Agents across multiple providers and transport protocols.
OmniVoice supports two fundamentally different approaches for real-time voice:
Audio In β [STT Provider] β Text β [LLM] β Text β [TTS Provider] β Audio Out
- Latency: 500-1500ms (sum of STT + LLM + TTS)
- Flexibility: Mix and match any STT, LLM, and TTS providers
- Use case: Custom voice selection, specialized STT for domain-specific terminology
Audio In β [OpenAI Realtime / Gemini Live] β Audio Out
- Latency: 100-200ms (model handles audio directly)
- Simplicity: Single API, no separate STT/TTS configuration
- Use case: Low-latency conversations, natural barge-in handling
| Aspect | Traditional | Native Voice-to-Voice |
|---|---|---|
| Latency | 500-1500ms | 100-200ms |
| STT/TTS Config | Required | Built-in |
| Core Interface | stt.Provider, tts.Provider |
realtime.Provider |
| Provider Packages | tts/, stt/ |
omni-openai/omnivoice/realtime, omni-google/omnivoice/realtime |
| Gateway Bridge | Pipeline-based | RealtimeBridge in gateway/ |
| Barge-in | Via bargein/ package |
Native support |
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β OmniVoice β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β βββββββββββββββ βββββββββββββββ βββββββββββββββββββββββββββββββββββ β
β β TTS β β STT β β Voice Agent β β
β β β β β β β β
β β Text β Audioβ β Audio β Textβ β Real-time bidirectional voice β β
β ββββββββ¬βββββββ ββββββββ¬βββββββ βββββββββββββββββ¬ββββββββββββββββββ β
β β β β β
β βΌ βΌ βΌ β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β Cloud Provider Layer β β
β βββββββββββββββ¬ββββββββββββββ¬ββββββββββββββ¬ββββββββββββββ¬ββββββββββββββ€ β
β β ElevenLabs β Deepgram β Google Cloudβ AWS β Azure β β
β β Cartesia β Whisper β AssemblyAI β Polly β Speech β β
β βββββββββββββββ΄ββββββββββββββ΄ββββββββββββββ΄ββββββββββββββ΄ββββββββββββββ β
β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β Local Provider Layer β β
β βββββββββββββββ¬ββββββββββββββ¬ββββββββββββββ¬ββββββββββββββ¬ββββββββββββββ€ β
β β F5-TTS β Whisper MLX β Piper β Apple TTS β (more) β β
β β (MLX) β (MLX) β (ONNX) β (macOS) β β β
β βββββββββββββββ΄ββββββββββββββ΄ββββββββββββββ΄ββββββββββββββ΄ββββββββββββββ β
β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β Transport Layer β β
β βββββββββββββββ¬ββββββββββββββ¬ββββββββββββββ¬ββββββββββββββ¬ββββββββββββββ€ β
β β WebRTC β SIP β PSTN β WebSocket β HTTP β β
β βββββββββββββββ΄ββββββββββββββ΄ββββββββββββββ΄ββββββββββββββ΄ββββββββββββββ β
β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β Call System Integration β β
β βββββββββββββββ¬ββββββββββββββ¬ββββββββββββββ¬ββββββββββββββ¬ββββββββββββββ€ β
β β Twilio β Telnyx β Vonage β Plivo β LiveKit β β
β βββββββββββββββ΄ββββββββββββββ΄ββββββββββββββ΄ββββββββββββββ΄ββββββββββββββ β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
omnivoice/
βββ tts/ # Text-to-Speech
β βββ tts.go # Interface definitions
β βββ elevenlabs/ # ElevenLabs provider
β βββ polly/ # AWS Polly provider
β βββ google/ # Google Cloud TTS
β βββ azure/ # Azure Speech
β βββ cartesia/ # Cartesia provider
β
βββ stt/ # Speech-to-Text
β βββ stt.go # Interface definitions
β βββ transcript.go # Canonical Transcript format
β βββ whisper/ # OpenAI Whisper
β βββ deepgram/ # Deepgram provider
β βββ google/ # Google Speech-to-Text
β βββ azure/ # Azure Speech
β βββ assemblyai/ # AssemblyAI provider
β
βββ terminology/ # Shared Pronouncer + CaseCorrector engine
β # (spoken form before TTS; displayed form after STT)
β # See docs/terminology.md
β
βββ schema/ # Embedded JSON Schemas
β βββ schema.go # //go:embed directives
β βββ transcript-v1.schema.json # Transcript format schema
β
βββ agent/ # Voice Agent orchestration
β βββ agent.go # Interface definitions
β βββ session.go # Conversation session management
β βββ elevenlabs/ # ElevenLabs Agents
β βββ vapi/ # Vapi.ai
β βββ retell/ # Retell AI
β βββ custom/ # Custom agent (STT + LLM + TTS)
β
βββ transport/ # Audio transport protocols
β βββ transport.go # Interface definitions
β βββ webrtc/ # WebRTC transport
β βββ websocket/ # WebSocket streaming
β βββ sip/ # SIP protocol
β βββ http/ # HTTP-based (batch)
β
βββ callsystem/ # Call system integrations
β βββ callsystem.go # Interface definitions
β βββ client.go # Multi-provider client with failover
β βββ sms.go # SMSProvider interface
β βββ twilio/ # Twilio ConversationRelay
β βββ ringcentral/ # RingCentral Voice API
β βββ zoom/ # Zoom SDK integration
β βββ livekit/ # LiveKit rooms
β βββ daily/ # Daily.co
β
βββ observability/ # Voice instrumentation
β βββ events.go # VoiceEvent, VoiceObserver
β βββ hooks.go # TTSHook, STTHook interfaces
β
βββ resilience/ # Error handling and retry logic
β βββ category.go # Error categories (transient, rate_limit, auth, etc.)
β βββ error.go # ProviderError with classification metadata
β βββ classifier.go # ErrorClassifier interface
β βββ retry.go # Retry and RetryWithResult functions
β βββ backoff.go # Backoff strategies (exponential, linear, etc.)
β
βββ storage/ # Session state persistence
β βββ store.go # SessionStore interface
β βββ types.go # SessionState, Turn, Metrics types
β βββ memory.go # In-memory implementation
β βββ redis.go # Redis implementation
β
βββ bargein/ # Barge-in detection
β βββ config.go # InterruptionMode (immediate, after_sentence, disabled)
β βββ detector.go # BargeInDetector with TTS/STT integration
β
βββ realtime/ # Native voice-to-voice
β βββ provider.go # Provider interface for OpenAI Realtime / Gemini Live
β βββ client.go # Multi-provider client with fallback
β βββ errors.go # Common realtime errors
β
βββ audio/ # Audio processing
β βββ format/ # Audio format definitions
β β βββ format.go # Encoding type with normalization, provider format constants
β βββ converter/ # Audio format conversion
β β βββ converter.go # TwilioToOpenAI, OpenAIToTwilio, etc.
β βββ codec/ # Audio codecs (mulaw, alaw, PCM)
β
βββ gateway/ # Voice gateway integration
β βββ gateway.go # Gateway, Session, Config interfaces
β βββ bridge.go # RealtimeBridge for telephony β realtime
β
βββ registry.go # Global provider registry (STT, TTS, CallSystem, Gateway, Realtime)
βββ registry/ # Provider discovery types
β βββ registry.go # Registry interface, factory types, Gateway/RealtimeProvider interfaces
β βββ options.go # ProviderConfig, ProviderOption (WithVoice, WithModel, etc.)
β
βββ providers/ # Built-in local provider implementations
β βββ f5tts-mlx/ # F5-TTS MLX local TTS provider
β β βββ f5tts.go # gRPC client implementing TTS interfaces
β β βββ server/ # Python gRPC server
β βββ whisper-mlx/ # Whisper MLX local STT provider
β βββ whisper.go # gRPC client implementing STT interfaces
β βββ server/ # Python gRPC server
β
βββ proto/ # Protocol Buffer definitions
β βββ localtts/v1/ # Local TTS service proto
β βββ localstt/v1/ # Local STT service proto
β βββ localvoice/v1/ # Unified local voice service proto
β
βββ config/ # Configuration utilities
β βββ paths.go # Voice profile directory paths
β
βββ voices/ # Voice profile management
β βββ library.go # Voice profile library (list, create, delete)
β
βββ cmd/omnictl/ # Development CLI tool
β βββ cmd/ # CLI commands (generate, server, voice, health)
β
βββ subtitle/ # Subtitle generation
β βββ subtitle.go # SRT/VTT from transcription results
β
βββ examples/
βββ simple-tts/ # Basic TTS example
βββ voice-agent/ # Voice agent with Twilio
βββ multi-provider/ # Provider fallback example
OmniVoice provides two gateway interfaces for different use cases:
For traditional phone calls via Twilio, Telnyx, Vonage, or Plivo:
type Gateway interface {
Name() ProviderName
Start(ctx context.Context) error
Stop() error
OnCall(handler CallHandler) // Phone call comes in
MakeCall(ctx, to string) (Session, error) // Dial phone number
GetSession(callID string) (Session, bool)
ListSessions() []Session
}For WebRTC-based voice via LiveKit, Daily, etc.:
type WebRTCGateway interface {
Name() ProviderName
Start(ctx context.Context) error
Stop() error
OnParticipantJoined(handler ParticipantHandler) // User joins room
JoinRoom(ctx, roomName string) error
LeaveRoom() error
CurrentRoom() string
GetSession(participantID string) (WebRTCSession, bool)
ListSessions() []WebRTCSession
GenerateClientToken(roomName, identity, displayName string) (string, error)
}| Aspect | Gateway (PSTN) |
WebRTCGateway |
|---|---|---|
| Connection | Phone number | Room name |
| Incoming | OnCall() |
OnParticipantJoined() |
| Outgoing | MakeCall(phoneNumber) |
JoinRoom(roomName) |
| Latency | 500ms+ | <200ms |
| Clients | Phone calls | Browser/mobile apps |
Voice AI agents need a transport layer to receive and send audio. The choice depends on the use case:
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Voice Gateway Providers (Bidirectional) β
ββββββββββββββββββ¬ββββββββββββββββ¬ββββββββββββββββββ¬βββββββββββββββββββββ€
β Platform β Protocol β Audio Format β Auth Method β
ββββββββββββββββββΌββββββββββββββββΌββββββββββββββββββΌβββββββββββββββββββββ€
β Twilio β Media Streams β mulaw 8kHz β Account SID/Token β
β Media Streams β WebSocket β β β
ββββββββββββββββββΌββββββββββββββββΌββββββββββββββββββΌβββββββββββββββββββββ€
β Telnyx β Media β L16 16kHz β API Key β
β Media Streamingβ WebSocket β β β
ββββββββββββββββββΌββββββββββββββββΌββββββββββββββββββΌβββββββββββββββββββββ€
β Vonage β Voice β L16 16kHz β JWT (RS256) β
β Voice WebSocketβ WebSocket β β β
ββββββββββββββββββΌββββββββββββββββΌββββββββββββββββββΌβββββββββββββββββββββ€
β Plivo β Stream API β L16 16kHz β Auth ID/Token β
β Audio Streamingβ WebSocket β β β
ββββββββββββββββββ΄ββββββββββββββββ΄ββββββββββββββββββ΄βββββββββββββββββββββ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Other Call System Options β
ββββββββββββββββββ¬ββββββββββββββββ¬ββββββββββββββββββ¬βββββββββββββββββββββ€
β Platform β Protocol β Best For β Complexity β
ββββββββββββββββββΌββββββββββββββββΌββββββββββββββββββΌβββββββββββββββββββββ€
β LiveKit β WebRTC β Custom apps, β Low - open source β
β β β real-time AI β WebRTC rooms β
ββββββββββββββββββΌββββββββββββββββΌββββββββββββββββββΌβββββββββββββββββββββ€
β Daily.co β WebRTC β Embedded video, β Low - simple API β
β β β browser-based β β
ββββββββββββββββββΌββββββββββββββββΌββββββββββββββββββΌβββββββββββββββββββββ€
β WebSocket β WS/WSS β Web apps, β Low - direct β
β (Direct) β β custom UIs β streaming β
ββββββββββββββββββ΄ββββββββββββββββ΄ββββββββββββββββββ΄βββββββββββββββββββββ
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β PSTN/WebSocket Call Flow β
β β
β βββββββββββ βββββββββββββββ βββββββββββββββββββββββββββββ β
β β User ββββββββββΊβ Provider βββββββββββΊβ OmniVoice β β
β β (Phone) β PSTN β (Twilio/ β WebSocketβ β β
β β β β Telnyx/ β β βββββββββββββββββββββββ β β
β βββββββββββ β Vonage/ β β β Voice Agent β β β
β β Plivo) β β β β β β
β βββββββββββββββ β β βββββββββ β β β
β Audio In ββββββββββββββΊβ β β STT ββββ β β β
β β β βββββββββ β β β β
β β β βΌ β β β
β β β βββββββββββββββββ β β β
β β β β LLM / Agent β β β β
β β β β (Eino, etc.) β β β β
β β β βββββββββββββββββ β β β
β β β β β β β
β β β βΌ β β β
β β β βββββββββ β β β
β Audio Out ββββββββββββββ β β TTS ββββ β β β
β β β βββββββββ β β β
β β βββββββββββββββββββββββ β β
β βββββββββββββββββββββββββββββ β
β β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Zoom Meeting Flow β
β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β Zoom Meeting β β
β β β β
β β βββββββββββ βββββββββββ βββββββββββ βββββββββββββββββββββββ β β
β β β User 1 β β User 2 β β User 3 β β Bot Client β β β
β β β (Human) β β (Human) β β (Human) β β (Zoom SDK) β β β
β β βββββββββββ βββββββββββ βββββββββββ ββββββββββββ¬βββββββββββ β β
β β β β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββΌβββββββββββββββ β
β β β
β Raw Audio Stream β β
β βΌ β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β OmniVoice Agent β β
β β β β
β β Option A: Use Recall.ai (recommended) β β
β β βββββββββββββββ β β
β β β Recall.ai ββββΊ Handles Zoom SDK complexity β β
β β β Bot ββββΊ Provides audio stream via WebSocket β β
β β βββββββββββββββ β β
β β β β
β β Option B: Self-hosted Zoom SDK Bot β β
β β βββββββββββββββ β β
β β β Zoom Linux ββββΊ Complex: requires native SDK β β
β β β SDK Bot ββββΊ One instance per meeting β β
β β ββββββββββββββββββΊ Months of engineering β β
β β β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
| Use Case | Call System | Transport | Notes |
|---|---|---|---|
| IVR / Call Center | Twilio, Telnyx, Plivo | PSTN/WebSocket | Managed infrastructure |
| International Calls | Plivo, Vonage | PSTN/WebSocket | Good international rates |
| Enterprise Voice | Vonage, Telnyx | PSTN/WebSocket | Flexible call control |
| Custom Web App | LiveKit or Daily | WebRTC | Open source, flexible |
| Browser Widget | Direct WebSocket | WebSocket | ElevenLabs widget or custom |
| Mobile App | LiveKit | WebRTC | Cross-platform support |
For natural conversation, total round-trip latency should be under 500ms:
User speaks β STT (100-300ms) β LLM (200-500ms) β TTS (100-200ms) β User hears
Target: < 500ms total for "instant" feel
Acceptable: < 1000ms for natural conversation
Poor: > 1500ms feels laggy
- Streaming STT: Start processing before user finishes speaking
- Streaming TTS: Start playing audio before full response generated
- Edge inference: Use providers with edge nodes (Deepgram, ElevenLabs)
- Turn detection: Use voice activity detection (VAD) for quick turn-taking
| Provider | Latency | Quality | Voices | Streaming | Price |
|---|---|---|---|---|---|
| ElevenLabs | Low | Excellent | 5000+ | Yes | $$$ |
| Cartesia | Very Low | Good | 100+ | Yes | $$ |
| AWS Polly | Low | Good | 60+ | Yes | $ |
| Google TTS | Low | Good | 200+ | Yes | $ |
| Azure Speech | Low | Excellent | 400+ | Yes | $$ |
| Provider | Model | Voice Cloning | Latency | Price |
|---|---|---|---|---|
| F5-TTS MLX | F5-TTS | Yes | ~500ms | Free |
| Whisper MLX | Whisper | N/A (STT) | ~200ms | Free |
| Piper | Piper | No | ~100ms | Free (planned) |
Local providers run on your hardware via gRPC over Unix Domain Socket:
import (
"github.com/plexusone/omnivoice"
_ "github.com/plexusone/omnivoice-core/providers/f5tts-mlx"
)
// Use F5-TTS for local synthesis
provider, _ := omnivoice.GetTTSProvider("f5tts-mlx")
// Load model (downloads ~2GB on first run)
if loader, ok := provider.(tts.ModelManager); ok {
loader.LoadModel(ctx)
}
// Synthesize locally - no API calls
result, _ := provider.Synthesize(ctx, "Hello from local TTS!", tts.SynthesisConfig{})Whisper MLX provides matching local STT (BCP-47 locales like en-US are
normalized to the ISO-639-1 code Whisper expects):
import (
"github.com/plexusone/omnivoice"
_ "github.com/plexusone/omnivoice-core/providers/whisper-mlx"
"github.com/plexusone/omnivoice-core/stt"
)
// Transcribe locally - no API calls
provider, _ := omnivoice.GetSTTProvider("whisper-mlx")
result, _ := provider.Transcribe(ctx, audioBytes, stt.TranscriptionConfig{
Language: "en-US",
EnableWordTimestamps: true,
})See the Local TTS Providers guide for setup instructions.
| Provider | Latency | Accuracy | Streaming | Languages | Price |
|---|---|---|---|---|---|
| Deepgram | Very Low | Excellent | Yes | 30+ | $$ |
| Whisper (OpenAI) | Medium | Excellent | No* | 50+ | $ |
| Google Speech | Low | Excellent | Yes | 125+ | $$ |
| AssemblyAI | Low | Excellent | Yes | 20+ | $$ |
| Azure Speech | Low | Excellent | Yes | 100+ | $$ |
*Whisper requires self-hosting for streaming (e.g., faster-whisper)
| Provider | Customization | Latency | Telephony | Price |
|---|---|---|---|---|
| ElevenLabs Agents | Medium | Low | Via Twilio | $$$ |
| Vapi | High | Low | Built-in | $$ |
| Retell AI | High | Low | Built-in | $$ |
| Custom (OmniVoice) | Full | Variable | Via integration | Variable |
OmniVoice includes conformance test suites that provider implementations can use to verify they correctly implement the TTS and STT interfaces with consistent behavior.
Provider implementations should import the providertest packages and run the conformance tests:
// In your provider's conformance_test.go
import (
"github.com/plexusone/omnivoice-core/stt/providertest"
// or for TTS:
// "github.com/plexusone/omnivoice-core/tts/providertest"
)
func TestConformance(t *testing.T) {
p, err := New(WithAPIKey(apiKey))
if err != nil {
t.Fatal(err)
}
providertest.RunAll(t, providertest.Config{
Provider: p,
TestAudioFile: "/path/to/test.mp3",
TestAudioURL: "https://example.com/test.mp3",
// ...
})
}| Category | Description | API Required |
|---|---|---|
| Interface | Verify provider implements interface contract (Name, etc.) | No |
| Behavior | Verify edge case handling (empty input, context cancellation) | Sometimes |
| Integration | Verify actual synthesis/transcription works | Yes |
| Test | Description |
|---|---|
Transcribe |
Batch transcription from audio bytes |
TranscribeFile |
Batch transcription from local file path |
TranscribeURL |
Batch transcription from remote URL |
TranscribeStream |
Real-time streaming transcription |
| Test | Description |
|---|---|
Synthesize |
Returns valid audio bytes |
SynthesizeStream |
Streams audio chunks |
SynthesizeFromReader |
Handles streaming text input |
See Provider Conformance Testing TRD for detailed design documentation.
The tts/providertest package includes mock providers and fixtures for testing TTS integrations without API keys:
import "github.com/plexusone/omnivoice-core/tts/providertest"
// Provider-specific mocks with realistic voices
elevenLabs := providertest.NewElevenLabsMock() // Rachel, Bella, Antoni
deepgram := providertest.NewDeepgramMock() // Asteria, Luna, Orion
openai := providertest.NewOpenAIMock() // Alloy, Echo, Fable, Onyx, Nova, Shimmer
// Configurable mock behaviors
mock := providertest.NewMockProviderWithOptions(
providertest.WithLatency(100 * time.Millisecond), // Simulate network delay
providertest.WithError(providertest.ErrMockRateLimit), // Error injection
providertest.WithFailAfterN(3, providertest.ErrMockQuotaExceeded), // Failover testing
)
// Generate valid WAV fixtures
fixture := providertest.GenerateWAVFixture(1000, 22050) // 1 second at 22050 HzFor lowest latency, use native voice-to-voice APIs that bypass traditional STT/TTS:
| Provider | Package | Latency | Audio Format |
|---|---|---|---|
| OpenAI Realtime | omni-openai/omnivoice/realtime |
~100ms | PCM16 24kHz |
| Gemini Live | omni-google/omnivoice |
~200ms | PCM16 16kHz in, 24kHz out |
These providers implement the RealtimeProvider interface:
type RealtimeProvider interface {
ProcessAudioStream(
ctx context.Context,
audioIn <-chan []byte,
config ProcessConfig,
) (<-chan AudioChunk, <-chan Transcript, error)
Name() string
}- LiveKit Voice AI
- Daily.co
- Recall.ai - Meeting bot infrastructure