Skip to content

livekit/server-sdk-go

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

The LiveKit icon, the name of the repository and some sample code in the background.

LiveKit Go SDK

Use this SDK to interact with LiveKit server APIs and create access tokens from your Go backend.

[!NOTE]

Version 2 of the SDK contains a small set of breaking changes. Read the migration guide for a detailed overview of what has changed.

Installation

go get github.com/livekit/server-sdk-go/v2

Note: since v1.0 release, this package requires Go 1.18+ in order to build.

Token creation

import (
	"time"

	lksdk "github.com/livekit/server-sdk-go/v2"
	"github.com/livekit/protocol/auth"
)

func getJoinToken(apiKey, apiSecret, room, identity string) (string, error) {
	at := auth.NewAccessToken(apiKey, apiSecret)
	grant := &auth.VideoGrant{
		RoomJoin: true,
		Room:     room,
	}
	at.SetVideoGrant(grant).
		SetIdentity(identity).
		SetValidFor(time.Hour)

	return at.ToJWT()
}

RoomService API

RoomService gives you complete control over rooms and participants within them. It includes selective track subscriptions as well as moderation capabilities.

import (
	lksdk "github.com/livekit/server-sdk-go/v2"
	livekit "github.com/livekit/protocol/livekit"
)

func main() {
	hostURL := "host-url"  // ex: https://project-123456.livekit.cloud
	apiKey := "api-key"
	apiSecret := "api-secret"

	roomName := "myroom"
	identity := "participantIdentity"

    roomClient := lksdk.NewRoomServiceClient(hostURL, apiKey, apiSecret)

    // create a new room
    room, _ := roomClient.CreateRoom(context.Background(), &livekit.CreateRoomRequest{
		Name: roomName,
	})

    // list rooms
    res, _ := roomClient.ListRooms(context.Background(), &livekit.ListRoomsRequest{})

    // terminate a room and cause participants to leave
    roomClient.DeleteRoom(context.Background(), &livekit.DeleteRoomRequest{
		Room: roomId,
	})

    // list participants in a room
    res, _ := roomClient.ListParticipants(context.Background(), &livekit.ListParticipantsRequest{
		Room: roomName,
	})

    // disconnect a participant from room
    roomClient.RemoveParticipant(context.Background(), &livekit.RoomParticipantIdentity{
		Room:     roomName,
		Identity: identity,
	})

    // mute/unmute participant's tracks
    roomClient.MutePublishedTrack(context.Background(), &livekit.MuteRoomTrackRequest{
		Room:     roomName,
		Identity: identity,
		TrackSid: "track_sid",
		Muted:    true,
	})
}

Interacting as a participant

The Real-time SDK gives you access programmatic access as a client enabling you to publish and record audio/video/data to the room.

import (
  lksdk "github.com/livekit/server-sdk-go/v2"
)

func main() {
  hostURL := "host-url"  // ex: https://project-123456.livekit.cloud
  apiKey := "api-key"
  apiSecret := "api-secret"
  roomName := "myroom"
  identity := "botuser"
  roomCB := &lksdk.RoomCallback{
	ParticipantCallback: lksdk.ParticipantCallback{
	  OnTrackSubscribed: trackSubscribed,
  	},
  }
  room, err := lksdk.ConnectToRoom(hostURL, lksdk.ConnectInfo{
  	APIKey:              apiKey,
  	APISecret:           apiSecret,
  	RoomName:            roomName,
  	ParticipantIdentity: identity,
  }, roomCB)
  if err != nil {
  	panic(err)
  }

  ...
  room.Disconnect()
}

func trackSubscribed(track *webrtc.TrackRemote, publication *lksdk.RemoteTrackPublication, rp *lksdk.RemoteParticipant) {

}

For more advanced usage, see the examples directory.

Publishing tracks to Room

With the Go SDK, you can publish existing files encoded in H.264, VP8, and Opus to the room.

First, you will need to encode media into the right format.

VP8 / Opus

ffmpeg -i <input.mp4> \
  -c:v libvpx -keyint_min 120 -qmax 50 -maxrate 2M -b:v 1M <output.ivf> \
  -c:a libopus -page_duration 20000 -vn <output.ogg>

The above encodes VP8 at average 1Mbps / max 2Mbps with a minimum keyframe interval of 120.

H.264 / Opus

ffmpeg -i <input.mp4> \
  -c:v libx264 -bsf:v h264_mp4toannexb -b:v 2M -profile baseline -pix_fmt yuv420p \
    -x264-params keyint=120 -max_delay 0 -bf 0 <output.h264> \
  -c:a libopus -page_duration 20000 -vn <output.ogg>

The above encodes H264 with CBS of 2Mbps with a minimum keyframe interval of 120.

Publish from file

file := "video.ivf"
videoWidth := 1920
videoHeight := 1080
track, err := lksdk.NewLocalFileTrack(file,
	// control FPS to ensure synchronization
	lksdk.ReaderTrackWithFrameDuration(33 * time.Millisecond),
	lksdk.ReaderTrackWithOnWriteComplete(func() { fmt.Println("track finished") }),
)
if err != nil {
    return err
}
if _, err = room.LocalParticipant.PublishTrack(track, &lksdk.TrackPublicationOptions{
	Name: file,
	VideoWidth: videoWidth,
	VideoHeight: videoHeight,
}); err != nil {
    return err
}

Publish from io.ReadCloser implementation

// - `in` implements io.ReadCloser, such as buffer or file
// - `mime` has to be one of webrtc.MimeType...
track, err := lksdk.NewLocalReaderTrack(in, mime,
	lksdk.ReaderTrackWithFrameDuration(33 * time.Millisecond),
	lksdk.ReaderTrackWithOnWriteComplete(func() { fmt.Println("track finished") }),
)
if err != nil {
	return err
}
if _, err = room.LocalParticipant.PublishTrack(track, &lksdk.TrackPublicationOptions{}); err != nil {
    return err
}

For a full working example, refer to filesender. This example sends all audio/video files in the current directory.

Publishing audio from PCM16 Samples

In order to publish audio from PCM16 Samples, you can use the NewPCMLocalTrack API as follows:

import (
	...
	lkmedia "github.com/livekit/server-sdk-go/v2/pkg/media"
)

...

publishTrack, err := lkmedia.NewPCMLocalTrack(sourceSampleRate, sourceChannels, logger.GetLogger())
if err != nil {
	return err
}

if _, err = room.LocalParticipant.PublishTrack(publishTrack, &lksdk.TrackPublicationOptions{
	Name: "test",
}); err != nil {
	return err
}

You can then write PCM16 samples to the publishTrack like:

err = publishTrack.WriteSample(sample)
if err != nil {
	logger.Errorw("error writing sample", err)
}

The SDK will encode the sample to Opus and write it to the track. If the sourceSampleRate is not 48000, resampling is also handled internally.

The API also provides an option to write silence to the track when no data is available, this is disabled by default but you can enable it using:

publishTrack, err := lkmedia.NewPCMLocalTrack(sourceSampleRate, sourceChannels, logger.GetLogger(), lkmedia.WithWriteSilenceOnNoData(true))

Note: Stereo audio is currently not supported, it may result in unpleasant audio.

Publish from other sources

In order to publish from non-file sources, you will have to implement your own SampleProvider, that could provide frames of data with a NextSample method.

The SDK takes care of sending the samples to the room.

Using a pacer

With video publishing, keyframes can be an order of magnitude larger than delta frames. This size difference can cause a significant increase in bitrate when a keyframe is transmitted, leading to a surge in packet flow. Such spikes might result in packet loss at the forwarding layer. To maintain a consistent packet flow, you can enable the use of a pacer.

import "github.com/livekit/mediatransportutil/pkg/pacer"

// Control total output bitrate to 10Mbps with 1s max latency
pf := pacer.NewPacerFactory(
	pacer.LeakyBucketPacer,
	pacer.WithBitrate(10000000),
	pacer.WithMaxLatency(time.Second),
)

room, err := lksdk.ConnectToRoom(hostURL, lksdk.ConnectInfo{
    APIKey:              apiKey,
    APISecret:           apiSecret,
    RoomName:            roomName,
    ParticipantIdentity: identity,
}, &lksdk.RoomCallback{
    ParticipantCallback: lksdk.ParticipantCallback{
        OnTrackSubscribed: onTrackSubscribed,
    },
}, lksdk.WithPacer(pf))

Receiving tracks from Room

With the Go SDK, you can accept media from the room.

For a full working example, refer to filesaver. This example saves the audio/video in the LiveKit room to the local disk.

Decoding an Opus track to PCM16

To get PCM audio out of a remote Opus audio track, you can use the following API:

import (
	...
	media "github.com/livekit/media-sdk"
	lkmedia "github.com/livekit/server-sdk-go/v2/pkg/media"
)

type PCM16Writer struct {
	closed atomic.Bool
}

func (w *PCM16Writer) WriteSample(sample media.PCM16Sample) error {
	if !w.closed.Load() {
		// Use the sample however you want
	}
}

func (w *PCM16Writer) SampleRate() int {
	// return the sample rate of the writer
	// the SDK will resample if the remote track is 
	// using a different sampling rate (48000 kHz)
}

func (w* PCM16Writer) Channels() int {
	// return the channel count of the writer
	// the sdk will then upmix/downmix the remote track accordingly
}

func (w *PCM16Writer) String() string {
	// return a desired string
	// can be used to monitor writer stages or config, etc.
}

func (w *PCM16Writer) Close() error {
	w.closed.Store(true)
	// close the writer
}

...

writer := &PCM16Writer{}
pcmTrack, err := lkmedia.NewPCMRemoteTrack(remoteTrack, writer)
if err != nil {
	return err
}

The SDK will then read the provided remote track, decode the audio and write the PCM16 samples to the provided writer. Resampling to the target sample rate is handled internally, and so is upmixing/downmixing to the target channel count.

The API also provides an option to handle jitter, this is enabled by default but you can disable it using:

pcmTrack, err := lkmedia.NewPCMRemoteTrack(remoteTrack, writer, lkmedia.WithHandleJitter(false))

Note: Stereo remote tracks are currently not supported, they may result in unpleasant audio.

Receiving webhooks

The Go SDK helps you to verify and decode webhook callbacks to ensure their authenticity. See webhooks guide for configuration.

import (
	"github.com/livekit/protocol/auth"
	"github.com/livekit/protocol/livekit"
	"github.com/livekit/protocol/webhook"
)

var authProvider = auth.NewSimpleKeyProvider(
	apiKey, apiSecret,
)

func ServeHTTP(w http.ResponseWriter, r *http.Request) {
  // event is a livekit.WebhookEvent{} object
	event, err := webhook.ReceiveWebhookEvent(r, authProvider)
	if err != nil {
		// could not validate, handle error
		return
	}

	// consume WebhookEvent
}


LiveKit Ecosystem
LiveKit SDKsBrowser · iOS/macOS/visionOS · Android · Flutter · React Native · Rust · Node.js · Python · Unity · Unity (WebGL)
Server APIsNode.js · Golang · Ruby · Java/Kotlin · Python · Rust · PHP (community) · .NET (community)
UI ComponentsReact · Android Compose · SwiftUI
Agents FrameworksPython · Node.js · Playground
ServicesLiveKit server · Egress · Ingress · SIP
ResourcesDocs · Example apps · Cloud · Self-hosting · CLI