Skip to content
Docs

LiveKit Transport Provider

The LiveKit provider implements bidirectional audio transport through LiveKit rooms. LiveKit is treated as a transport layer — it provides WebRTC connectivity while Beluga handles all STT, LLM, and TTS processing through the frame-based pipeline.

Choose LiveKit when you need a self-hostable, open-source WebRTC infrastructure for production voice deployments. LiveKit provides room management, access token authentication, and scalable media routing. Beluga treats LiveKit as a pure transport layer, handling all voice processing in the frame-based pipeline. For a managed alternative, consider Daily.

Terminal window
go get github.com/lookatitude/beluga-ai/v2/voice/transport/providers/livekit
FieldRequiredDefaultDescription
URLYes—LiveKit server URL (wss://...)
TokenYes—LiveKit access token
SampleRateNo16000Audio sample rate in Hz
ChannelsNo1Audio channels (1=mono, 2=stereo)

Extra configuration:

KeyTypeDescription
roomstringLiveKit room name to join
package main
import (
"context"
"fmt"
"log"
"github.com/lookatitude/beluga-ai/v2/voice/transport"
_ "github.com/lookatitude/beluga-ai/v2/voice/transport/providers/livekit"
)
func main() {
t, err := transport.New("livekit", transport.Config{
URL: "wss://myapp.livekit.cloud",
Token: "your-livekit-token",
Extra: map[string]any{
"room": "voice-room",
},
})
if err != nil {
log.Fatal(err)
}
defer t.Close()
// Receive incoming audio frames
for frame, err := range t.Recv(context.Background()) {
if err != nil {
log.Fatal(err)
}
fmt.Printf("Received %d bytes of audio\n", len(frame.Data))
}
}

Write processed audio back to the LiveKit room using voice.NewAudioFrame:

frame := voice.NewAudioFrame(processedPCM, 16000)
err := t.Send(ctx, frame)
if err != nil {
log.Printf("send failed: %v", err)
}

Pass the room name through the Extra map:

t, err := transport.New("livekit", transport.Config{
URL: "wss://myapp.livekit.cloud",
Token: token,
Extra: map[string]any{
"room": "my-voice-room",
},
})

Wrap the transport for use with Beluga’s voice pipeline:

import "github.com/lookatitude/beluga-ai/v2/voice/transport"
audioTransport, err := transport.New("livekit", cfg)
if err != nil {
log.Fatal(err)
}
voiceTransport := &transport.AsVoiceTransport{T: audioTransport}
// Use voiceTransport with the voice pipeline
import "github.com/lookatitude/beluga-ai/v2/voice/transport/providers/livekit"
t, err := livekit.New(transport.Config{
URL: "wss://myapp.livekit.cloud",
Token: "your-livekit-token",
SampleRate: 16000,
Channels: 1,
Extra: map[string]any{"room": "voice-room"},
})

transport.New("livekit", ...) currently always fails with an error wrapping transport.ErrNotImplemented, so check for it and fall back to a working transport:

t, err := transport.New("livekit", cfg)
if errors.Is(err, transport.ErrNotImplemented) {
// livekit is not implemented yet; use the built-in WebSocket transport
t, err = transport.NewWebSocketTransport(ctx, wsURL)
}
if err != nil {
log.Fatal(err)
}
defer t.Close()

Refer to the LiveKit documentation for server setup, room management, and token generation.