OmniMeet Integration¶
omni-livekit provides the LiveKit implementation for OmniMeet, the PlexusOne meeting abstraction.
Overview¶
OmniMeet provides a unified API for real-time meetings across platforms (LiveKit, Daily, Zoom, etc.). Using OmniMeet allows you to:
- Write provider-agnostic code
- Switch between LiveKit and other providers
- Use the OmniAgent meeting skill
Basic Usage¶
Import the Provider¶
import (
"github.com/plexusone/omni-livekit/omnimeet"
omnimeetcore "github.com/plexusone/omnimeet-core"
"github.com/plexusone/omnimeet-core/meeting"
)
Create Provider¶
provider, err := omnimeet.NewProvider(omnimeet.Config{
APIKey: os.Getenv("LIVEKIT_API_KEY"),
APISecret: os.Getenv("LIVEKIT_API_SECRET"),
ServerURL: os.Getenv("LIVEKIT_URL"),
})
if err != nil {
log.Fatal(err)
}
defer provider.Close()
Create Meeting¶
m, err := provider.CreateMeeting(ctx, meeting.CreateRequest{
Name: "Team Standup",
Metadata: map[string]string{
"team": "engineering",
},
})
if err != nil {
log.Fatal(err)
}
log.Printf("Meeting ID: %s", m.ID)
Generate Join Tokens¶
import (
"github.com/plexusone/omnimeet-core/token"
"github.com/plexusone/omnimeet-core/participant"
)
// Human participant
humanToken, _ := provider.CreateJoinToken(ctx, token.CreateRequest{
MeetingID: m.ID,
Participant: participant.Info{
Name: "Alice",
Kind: participant.KindHuman,
Identity: "alice@example.com",
},
})
log.Printf("Human join URL: %s", humanToken.JoinURL)
// Agent participant
agentToken, _ := provider.CreateJoinToken(ctx, token.CreateRequest{
MeetingID: m.ID,
Participant: participant.Info{
Name: "AI Assistant",
Kind: participant.KindAgent,
Identity: "ai-assistant",
},
})
Join as Agent¶
import "github.com/plexusone/omnimeet-core/provider"
// Get agent factory
factory := provider.(omnimeetcore.AgentParticipantFactory)
// Create agent participant
agent, err := factory.CreateAgentParticipant(provider.AgentParticipantOptions{
AutoSubscribe: true,
})
if err != nil {
log.Fatal(err)
}
// Set up event handlers
agent.OnParticipantJoined(func(p participant.Participant) {
log.Printf("Participant joined: %s (%s)", p.Name, p.Kind)
})
agent.OnParticipantLeft(func(p participant.Participant) {
log.Printf("Participant left: %s", p.Name)
})
// Join the meeting
if err := agent.JoinMeeting(ctx, m.ID, agentToken); err != nil {
log.Fatal(err)
}
defer agent.LeaveMeeting(ctx)
With Voice Integration¶
Use OmniMeet's voice package with OmniVoice providers:
import (
"github.com/plexusone/omnimeet-core/voice"
"github.com/plexusone/omnivoice"
"github.com/plexusone/omnivoice-core/stt"
"github.com/plexusone/omnivoice-core/tts"
_ "github.com/plexusone/omnivoice/providers/all"
)
// Get providers
sttProv, _ := omnivoice.GetSTTProvider("deepgram",
omnivoice.WithAPIKey(os.Getenv("DEEPGRAM_API_KEY")),
)
ttsProv, _ := omnivoice.GetTTSProvider("openai",
omnivoice.WithAPIKey(os.Getenv("OPENAI_API_KEY")),
)
// Wrap agent with voice capabilities
voiceAgent := voice.NewVoiceAgentParticipant(agent, voice.Config{
STTProvider: sttProv,
TTSProvider: ttsProv,
STTConfig: stt.TranscriptionConfig{
Language: "en",
SampleRate: 16000,
},
TTSConfig: tts.SynthesisConfig{
VoiceID: "alloy",
SampleRate: 48000,
},
OnTranscript: func(participantID, participantName, text string, isFinal bool) {
if isFinal {
log.Printf("%s: %s", participantName, text)
// Process and respond
response := processWithLLM(text)
voiceAgent.Speak(ctx, response)
}
},
})
// Start transcribing all human participants
voiceAgent.StartTranscribingAll(ctx)
Using MeetingSkill (OmniAgent)¶
For OmniAgent integration, use the meeting skill:
import "github.com/plexusone/omnimeet-core/agent"
// Create voice-enabled meeting skill
skill, err := agent.NewVoiceMeetingSkill(
provider,
agent.SkillConfig{
DefaultMeetingName: "AI Meeting",
DefaultAgentName: "Assistant",
AutoJoinAsAgent: true,
TranscriptionEnabled: true,
},
agent.VoiceSkillConfig{
STTProvider: sttProv,
TTSProvider: ttsProv,
STTConfig: stt.TranscriptionConfig{
Language: "en",
SampleRate: 16000,
},
TTSConfig: tts.SynthesisConfig{
VoiceID: "rachel",
SampleRate: 48000,
},
OnTranscript: func(meetingID, participantID, participantName, text string, isFinal bool) {
// Handle transcripts
},
},
)
if err != nil {
log.Fatal(err)
}
defer skill.Close()
// Initialize
skill.Init(ctx)
// Available tools
for _, tool := range skill.Tools() {
log.Printf("Tool: %s - %s", tool.Name(), tool.Description())
}
// Tools include:
// - create_meeting
// - list_meetings
// - get_meeting
// - join_meeting
// - leave_meeting
// - get_participants
// - speak_in_meeting
// - get_transcript
// - end_meeting
Provider Registration¶
You can also use the OmniMeet registry:
import (
omnimeet "github.com/plexusone/omnimeet-core"
_ "github.com/plexusone/omni-livekit/omnimeet" // Register provider
)
// Get provider from registry
provider, err := omnimeet.GetMeetingProvider("livekit",
omnimeet.WithAPIKey(os.Getenv("LIVEKIT_API_KEY")),
omnimeet.WithAPISecret(os.Getenv("LIVEKIT_API_SECRET")),
omnimeet.WithServerURL(os.Getenv("LIVEKIT_URL")),
)
Complete Example¶
package main
import (
"context"
"log"
"os"
"os/signal"
"syscall"
"github.com/plexusone/omni-livekit/omnimeet"
"github.com/plexusone/omnimeet-core/meeting"
"github.com/plexusone/omnimeet-core/participant"
"github.com/plexusone/omnimeet-core/provider"
"github.com/plexusone/omnimeet-core/token"
"github.com/plexusone/omnimeet-core/voice"
"github.com/plexusone/omnivoice"
"github.com/plexusone/omnivoice-core/stt"
"github.com/plexusone/omnivoice-core/tts"
_ "github.com/plexusone/omnivoice/providers/all"
)
func main() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
// Handle shutdown
sigCh := make(chan os.Signal, 1)
signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM)
go func() { <-sigCh; cancel() }()
// Create provider
prov, _ := omnimeet.NewProvider(omnimeet.Config{
APIKey: os.Getenv("LIVEKIT_API_KEY"),
APISecret: os.Getenv("LIVEKIT_API_SECRET"),
ServerURL: os.Getenv("LIVEKIT_URL"),
})
defer prov.Close()
// Create meeting
m, _ := prov.CreateMeeting(ctx, meeting.CreateRequest{
Name: "Demo Meeting",
})
log.Printf("Meeting: %s", m.ID)
// Generate human join URL
humanTok, _ := prov.CreateJoinToken(ctx, token.CreateRequest{
MeetingID: m.ID,
Participant: participant.Info{Name: "Human", Kind: participant.KindHuman},
})
log.Printf("Human join: %s", humanTok.JoinURL)
// Create agent
factory := prov.(provider.AgentParticipantFactory)
agent, _ := factory.CreateAgentParticipant(provider.AgentParticipantOptions{
AutoSubscribe: true,
})
// Get voice providers
sttProv, _ := omnivoice.GetSTTProvider("deepgram",
omnivoice.WithAPIKey(os.Getenv("DEEPGRAM_API_KEY")))
ttsProv, _ := omnivoice.GetTTSProvider("openai",
omnivoice.WithAPIKey(os.Getenv("OPENAI_API_KEY")))
// Wrap with voice
voiceAgent := voice.NewVoiceAgentParticipant(agent, voice.Config{
STTProvider: sttProv,
TTSProvider: ttsProv,
STTConfig: stt.TranscriptionConfig{SampleRate: 16000},
TTSConfig: tts.SynthesisConfig{VoiceID: "alloy", SampleRate: 48000},
OnTranscript: func(_, name, text string, isFinal bool) {
if isFinal {
log.Printf("%s: %s", name, text)
voiceAgent.Speak(ctx, "I heard: "+text)
}
},
})
// Generate agent token and join
agentTok, _ := prov.CreateJoinToken(ctx, token.CreateRequest{
MeetingID: m.ID,
Participant: participant.Info{Name: "AI", Kind: participant.KindAgent},
})
agent.JoinMeeting(ctx, m.ID, agentTok)
defer agent.LeaveMeeting(ctx)
// Start transcribing
voiceAgent.StartTranscribingAll(ctx)
log.Println("Running... Ctrl+C to exit")
<-ctx.Done()
}