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/voice/transport/providers/livekit
FieldRequiredDefaultDescription
URLYesLiveKit server URL (wss://...)
TokenYesLiveKit 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/voice/transport"
_ "github.com/lookatitude/beluga-ai/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
frames, err := t.Recv(context.Background())
if err != nil {
log.Fatal(err)
}
for frame := range frames {
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/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/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"},
})
t, err := transport.New("livekit", transport.Config{
URL: "wss://myapp.livekit.cloud",
// Missing Token
})
if err != nil {
// "livekit: Token is required"
log.Fatal(err)
}

Both URL and Token are required. The transport returns errors from Recv and Send if Close has already been called.

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