Skip to content
Docs

Daily Transport Provider

The Daily provider implements bidirectional audio transport through Daily.co rooms. It enables voice pipelines to send and receive audio via Daily’s WebRTC infrastructure.

Choose Daily when you want a managed WebRTC service with simple room-based audio transport. Daily handles the WebRTC infrastructure, letting you focus on voice pipeline logic. For self-hosted WebRTC infrastructure, consider LiveKit. For interoperability with Pipecat-based processing systems, consider Pipecat.

Terminal window
go get github.com/lookatitude/beluga-ai/v2/voice/transport/providers/daily
FieldRequiredDefaultDescription
URLYes—Daily.co room URL
TokenNo—Daily room token for authentication
SampleRateNo16000Audio sample rate in Hz
package main
import (
"context"
"fmt"
"log"
"github.com/lookatitude/beluga-ai/v2/voice/transport"
_ "github.com/lookatitude/beluga-ai/v2/voice/transport/providers/daily"
)
func main() {
t, err := transport.New("daily", transport.Config{
URL: "https://myapp.daily.co/room-name",
Token: "your-daily-token",
})
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 frames back to the Daily room using voice.NewAudioFrame:

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

For direct audio piping without frame wrapping:

writer := t.AudioOut()
_, err := writer.Write(rawPCMData)
if err != nil {
log.Printf("audio write failed: %v", err)
}
import "github.com/lookatitude/beluga-ai/v2/voice/transport/providers/daily"
t, err := daily.New(transport.Config{
URL: "https://myapp.daily.co/room-name",
Token: "your-daily-token",
SampleRate: 16000,
})

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

t, err := transport.New("daily", cfg)
if errors.Is(err, transport.ErrNotImplemented) {
// daily 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 Daily.co documentation for room setup and token generation.