omni-livekit

module
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 6, 2026 License: MIT

README

Omni-LiveKit

Go CI Go Lint Go SAST Docs Docs Visualization License

LiveKit voice gateway for WebRTC-based voice AI applications.

Overview

LiveKit provides pure WebRTC voice without phone network involvement. While PSTN gateways (Twilio, Telnyx, Vonage, Plivo) also offer WebRTC SDKs, they primarily bridge browser/app connections to the phone network. LiveKit is designed for direct browser-to-browser and app-to-app communication.

┌───────────────┐        ┌─────────────────┐        ┌───────────────────┐
│  Browser/App  │◄──────►│  LiveKit Cloud  │◄──────►│   OmniVoice       │
│   (WebRTC)    │ WebRTC │    or Server    │ WebRTC │   Voice Gateway   │
└───────────────┘        └─────────────────┘        └───────────────────┘

Use Cases

Use Case PSTN Gateways LiveKit
Phone calls (PSTN) Yes No
Browser WebRTC Yes (bridges to PSTN) Yes (native)
Mobile apps WebRTC SDK available WebRTC SDK available
Browser-to-browser Via PSTN bridge Direct WebRTC
Latency 300-500ms (PSTN hop) <200ms
Cost model Per-minute telephony Infrastructure only

Installation

go get github.com/plexusone/omni-livekit
Native Dependencies

This package requires native audio libraries for Opus encoding/decoding and resampling:

macOS:

brew install opus opusfile libsoxr

Ubuntu/Debian:

apt-get install libopus-dev libopusfile-dev libsoxr-dev

Fedora:

dnf install opus-devel opusfile-devel soxr-devel
Build Tags

Voice agents must be built with -tags opus to enable proper Opus codec support:

# Required for voice agents
go run -tags opus ./cmd/voice-agent
go build -tags opus ./cmd/voice-agent

# Without -tags opus, audio won't be decoded properly and STT will fail

Quick Start

Go Backend (AI Agent)
package main

import (
    "context"
    "log"
    "os"

    "github.com/plexusone/omni-livekit/omnivoice/gateway"
    coregateway "github.com/plexusone/omnivoice-core/gateway"
)

func main() {
    // Create gateway implementing coregateway.WebRTCGateway interface
    gw, err := gateway.New(gateway.Config{
        LiveKitURL:    os.Getenv("LIVEKIT_URL"),
        LiveKitAPIKey: os.Getenv("LIVEKIT_API_KEY"),
        LiveKitSecret: os.Getenv("LIVEKIT_API_SECRET"),
        RoomName:      "voice-agent",
        AgentIdentity: "ai-agent",
        SampleRate:    24000,
    })
    if err != nil {
        log.Fatal(err)
    }

    // Handle participant joins (WebRTC-specific handler)
    gw.OnParticipantJoined(func(p *coregateway.ParticipantInfo) error {
        log.Printf("Participant joined: %s (%s)", p.DisplayName, p.Identity)
        return nil // Accept participant
    })

    ctx := context.Background()
    if err := gw.Start(ctx); err != nil {
        log.Fatal(err)
    }
}
Generate Client Token
import "github.com/plexusone/omni-livekit/room"

client, _ := room.NewClient(room.Config{
    APIKey:    os.Getenv("LIVEKIT_API_KEY"),
    APISecret: os.Getenv("LIVEKIT_API_SECRET"),
    URL:       os.Getenv("LIVEKIT_URL"),
})

// Generate token for web/mobile client
token, _ := client.GenerateClientToken("voice-agent", "user-123", "John")
React Frontend
import { LiveKitRoom, useVoiceAssistant } from '@livekit/components-react';

function VoiceAgent() {
    const token = await fetchTokenFromBackend();

    return (
        <LiveKitRoom
            serverUrl={process.env.LIVEKIT_URL}
            token={token}
            connect={true}
            audio={true}
        >
            <VoiceUI />
        </LiveKitRoom>
    );
}

Interface

omni-livekit implements the coregateway.WebRTCGateway interface from omnivoice-core:

type WebRTCGateway interface {
    Name() ProviderName
    Start(ctx context.Context) error
    Stop() error
    OnParticipantJoined(handler ParticipantHandler)
    JoinRoom(ctx context.Context, roomName string) error
    LeaveRoom() error
    CurrentRoom() string
    GetSession(participantID string) (WebRTCSession, bool)
    ListSessions() []WebRTCSession
    GenerateClientToken(roomName, identity, displayName string) (string, error)
}

This is different from the Gateway interface used by PSTN providers (Twilio, Telnyx, etc.) which uses phone numbers and MakeCall().

Architecture

Audio Flow
Client (Browser/Mobile)
    │
    ▼ WebRTC Audio Track (Opus)
    │
┌───────────────────────────────────────┐
│           LiveKit Server              │
└───────────────────────────────────────┘
    │
    ▼ WebRTC Audio Track (Opus)
    │
┌───────────────────────────────────────┐
│       Go Backend (omni-livekit)       │
│                                       │
│  ┌─────────────────────────────────┐  │
│  │  PCMRemoteTrack                 │  │
│  │  (Opus → PCM16 decode)          │  │
│  └─────────────┬───────────────────┘  │
│                ▼                      │
│  ┌─────────────────────────────────┐  │
│  │  Voice Pipeline                 │  │
│  │  STT → LLM → TTS                │  │
│  │  (or Voice-to-Voice)            │  │
│  └─────────────┬───────────────────┘  │
│                ▼                      │
│  ┌─────────────────────────────────┐  │
│  │  PCMLocalTrack                  │  │
│  │  (PCM16 → Opus encode)          │  │
│  └─────────────────────────────────┘  │
└───────────────────────────────────────┘
Key Differences from PSTN Gateways
Aspect PSTN Gateways LiveKit
Primary use Phone network access Browser/app-to-app
Connection model Phone number dialing Room-based participation
Signaling HTTP webhooks + WebRTC WebRTC/WebSocket
Audio format mulaw 8kHz (PSTN), Opus (WebRTC) Opus (configurable rate)
Identity Phone number or SIP URI Participant ID
Session model Call legs (inbound/outbound) Room participants

Human Participation

When an AI agent joins a LiveKit room, humans can join via several methods:

Option 1: LiveKit Meet (No Code Required)

LiveKit provides a free hosted web UI. Generate a join URL with token:

// Generate token and URL
token, _ := client.GenerateClientToken("my-room", "user-123", "Alice")
joinURL := fmt.Sprintf("https://meet.livekit.io/custom?liveKitUrl=%s&token=%s",
    url.QueryEscape(serverURL), token)
// Share joinURL with the human participant

The human opens the link in their browser, grants mic/camera permissions, and joins.

Option 2: LiveKit Cloud Dashboard

If using LiveKit Cloud, create rooms and generate join links from the dashboard UI.

Option 3: Custom Frontend

Build your own UI with LiveKit's client SDKs:

Platform SDK Install
Web (JS/TS) livekit-client npm install livekit-client
React @livekit/components-react npm install @livekit/components-react
iOS LiveKit Swift SDK Swift Package Manager
Android LiveKit Android SDK Maven
Flutter livekit_client pub.dev

React Example:

import { LiveKitRoom, VideoConference } from '@livekit/components-react';
import '@livekit/components-styles';

function MeetingRoom({ token, serverUrl }) {
  return (
    <LiveKitRoom token={token} serverUrl={serverUrl} connect={true}>
      <VideoConference />
    </LiveKitRoom>
  );
}

Minimal HTML/JS:

<script src="https://unpkg.com/livekit-client/dist/livekit-client.umd.js"></script>
<script>
  const room = new LivekitClient.Room();
  await room.connect('wss://your-server.livekit.cloud', token);

  // Enable microphone
  await room.localParticipant.setMicrophoneEnabled(true);
</script>
Recommendation
Use Case Recommended Approach
Testing/Demos LiveKit Meet
Quick prototype LiveKit React components
Production app Custom frontend with full UX control

Environment Variables

# LiveKit Cloud or self-hosted server
export LIVEKIT_URL="wss://your-app.livekit.cloud"
export LIVEKIT_API_KEY="your-api-key"
export LIVEKIT_API_SECRET="your-api-secret"

Audio Configuration

The gateway supports configurable sample rates for optimal voice AI performance:

gateway.Config{
    SampleRate: 24000,  // 24kHz for high quality (OpenAI Realtime API)
    // SampleRate: 16000, // 16kHz for most STT/TTS
    Channels: 1,        // Mono audio
}

Session Events

session, ok := gw.GetSession(participantID)
if !ok {
    return
}

// WebRTCSession provides participant info
fmt.Printf("Room: %s\n", session.RoomName())
fmt.Printf("Participant: %s\n", session.Participant().DisplayName)

// Handle events
for event := range session.Events() {
    switch event.Type {
    case coregateway.EventUserTranscript:
        fmt.Printf("User said: %s\n", event.Data)
    case coregateway.EventAgentTranscript:
        fmt.Printf("Agent said: %s\n", event.Data)
    case coregateway.EventInterruption:
        fmt.Println("User interrupted agent")
    }
}

// Send audio to participant
samples := make([]int16, 480) // 20ms at 24kHz
session.SendAudio(samples)

Integration with OmniVoice

import (
    "github.com/plexusone/omni-livekit/omnivoice/gateway"
    "github.com/plexusone/omnivoice"
    _ "github.com/plexusone/omnivoice/providers/all"
)

// Use OmniVoice for STT/TTS
stt, _ := omnivoice.GetSTTProvider("deepgram", omnivoice.WithAPIKey(apiKey))
tts, _ := omnivoice.GetTTSProvider("elevenlabs", omnivoice.WithAPIKey(apiKey))

// LiveKit gateway receives audio → STT → LLM → TTS → sends audio
Voice Pipeline Modes

Standard Pipeline (STT → LLM → TTS):

Audio In → STT → Text → LLM → Text → TTS → Audio Out

This mode uses separate providers for speech-to-text, language model, and text-to-speech.

Voice-to-Voice (Lower Latency):

Audio In → Voice Model → Audio Out

OmniVoice supports direct voice-to-voice with:

  • Deepgram - Nova-3 Voice Agent
  • Google - Gemini Live
  • OpenAI - Realtime API

Voice-to-voice eliminates the text intermediate step, reducing latency for real-time conversations.

Lip-Sync Avatars

For realistic talking head video, integrate with Tavus using the tavus-go SDK:

import "github.com/plexusone/omni-livekit/avatar/tavus"

client, _ := tavus.NewClient(tavus.ClientConfig{
    APIKey: os.Getenv("TAVUS_API_KEY"),
})

// Create conversation with LiveKit transport
resp, _ := client.CreateConversation(ctx, tavus.CreateConversationRequest{
    PalID:        "your-pal-id",
    LiveKitURL:   os.Getenv("LIVEKIT_URL"),
    LiveKitToken: avatarToken,
})

The avatar joins the LiveKit room as a participant with synchronized lip movements.

OmniMeet Integration

This package also provides the LiveKit provider for OmniMeet, the PlexusOne meeting abstraction.

import "github.com/plexusone/omni-livekit/omnimeet"

provider, _ := omnimeet.NewProvider(omnimeet.Config{
    APIKey:    os.Getenv("LIVEKIT_API_KEY"),
    APISecret: os.Getenv("LIVEKIT_API_SECRET"),
    ServerURL: os.Getenv("LIVEKIT_URL"),
})

// Create meeting
m, _ := provider.CreateMeeting(ctx, meeting.CreateRequest{
    Name: "Team Standup",
})

// Join as agent
factory := provider.(provider.AgentParticipantFactory)
agent, _ := factory.CreateAgentParticipant(provider.AgentParticipantOptions{
    AutoSubscribe: true,
})

See the OmniMeet LiveKit Provider documentation for details.

License

MIT License

Directories

Path Synopsis
Package agent provides a full-featured LiveKit agent implementation.
Package agent provides a full-featured LiveKit agent implementation.
Package avatar provides lip-sync avatar support for omni-livekit voice agents.
Package avatar provides lip-sync avatar support for omni-livekit voice agents.
tavus
Package tavus provides Tavus avatar integration for omni-livekit voice agents.
Package tavus provides Tavus avatar integration for omni-livekit voice agents.
cmd
agent-demo command
Command agent-demo demonstrates a LiveKit AI agent that joins a room and interacts with human participants.
Command agent-demo demonstrates a LiveKit AI agent that joins a room and interacts with human participants.
audio-test command
Simple audio test - generates a tone to verify audio output works
Simple audio test - generates a tone to verify audio output works
encode-avatar command
Command encode-avatar pre-encodes an image as H.264 for use as a static avatar.
Command encode-avatar pre-encodes an image as H.264 for use as a static avatar.
voice-agent command
Command voice-agent demonstrates a full voice AI agent using LiveKit.
Command voice-agent demonstrates a full voice AI agent using LiveKit.
Package omnimeet provides a LiveKit implementation of the OmniMeet provider interface.
Package omnimeet provides a LiveKit implementation of the OmniMeet provider interface.
omnivoice
gateway
Package gateway provides a WebRTC voice gateway using LiveKit for real-time browser and mobile voice AI applications.
Package gateway provides a WebRTC voice gateway using LiveKit for real-time browser and mobile voice AI applications.
Package room provides utilities for working with LiveKit rooms.
Package room provides utilities for working with LiveKit rooms.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL