Participant metadata
LiveKit participants feature a metadata field, which allows you to store application-specific data. This can encompass various participant-related information, such as a URL to a participant's avatar or other unique participant attributes.
Metadata is encoded in the access token that participants use to connect to the room.
With our server SDKs, you can update any participant's metadata from your backend. LiveKit will broadcast metadata changes to all participants in the room. You can receive these updates by listening to the MetadataUpdated callback/event.
Example: Updating metadata from server API
import { RoomServiceClient } from 'livekit-server-sdk';const client = new RoomServiceClient("myhost", "api-key", "my secret")const data = JSON.stringify({some: "values",})client.updateParticipant("myroom", "participant-identity", data)
import (lksdk "github.com/livekit/server-sdk-go")func updateMetadata(values interface{}) {roomClient := lksdk.NewRoomServiceClient(host, apiKey, apiSecret)data, err := json.Marshal(values)_, err = roomClient.UpdateParticipant(context.Background(), &livekit.UpdateParticipantRequest{Room: "myroom",Identity: "participant-identity",Metadata: string(data),})}
Example: Updating metadata from client
When canUpdateOwnMetadata
permission is granted, a participant could also update their own name and metadata from client SDKs.
const data = JSON.stringify({some: "values",})room.localParticipant.setMetadata(data)room.localParticipant.setName('new name')
Data messages
From both server and clients, LiveKit lets you publish arbitrary data messages to any participants in the room via the LocalParticipant.publishData
API. Room data is published to the SFU via WebRTC data channels; and LiveKit server would forward that data to one or more participants in the room.
From the server side, this API is exposed on RoomService
as SendData
Since the data is sent via UDP, you have a flexibility in regard to the reliability of delivery. We support both reliable and lossy. In reliable mode, your packets will be retransmitted until they are received. For use-cases such as in-room chat, this is preferable.
When using lossy delivery, we suggest keeping data packets small (under network MTU of 1.4k). If a message is packetized into multiple packets, and a single packet doesn't arrive, your client will not receive the message at all.
const strData = JSON.stringify({some: "data"})const encoder = new TextEncoder()const decoder = new TextDecoder()// publishData takes in a Uint8Array, so we need to convert itconst data = encoder.encode(strData);// publish lossy data to the entire roomroom.localParticipant.publishData(data, DataPacket_Kind.LOSSY)// publish reliable data to a set of participantsroom.localParticipant.publishData(data, DataPacket_Kind.RELIABLE, ['participant_sid'])// receive data from other participantsroom.on(RoomEvent.DataReceived, (payload: Uint8Array, participant: Participant, kind: DataPacket_Kind) => {const strData = decoder.decode(payload)...})
import LiveKitpublic class DataExample {func publishData(localParticipant: LocalParticipant) {val someVal = "your value"// publish lossy data to the entire roomlocalParticipant.publish(data: someVal.data(using: .utf8), reliability: .lossy)// publish reliable data to a set of participantslocalParticipant.publish(data: someVal.data(using: .utf8), reliability: .reliable, ["sid1", "sid2"])}}extension DataExample: RoomDelegate {func room(_ room: Room, participant: RemoteParticipant, didReceive data: Data) {}}
class DataExample : RoomListener {fun publishData(localParticipant: LocalParticipant, data: ByteArray) {// publish lossy data to the entire roomlocalParticipant.publishData(data, DataPublishReliability.LOSSY)// publish reliable data to a set of participantslocalParticipant.publishData(data, DataPublishReliability.RELIABLE, listOf("sid1", "sid2"))}override fun onDataReceived(data: ByteArray, participant: RemoteParticipant, room: Room) {} {// process received data}}
class DataExample {Room room;late final _listener = room.createListener();DataExample() {_listener.on<DataReceivedEvent>((e) {// process received data: e.data})}void publishData() {// publish lossy data to the entire roomroom.localParticipant.publishData(data, DataPacket_Kind.LOSSY);// publish reliable data to a set of participantsroom.localParticipant.publishData(data, DataPacket_Kind.RELIABLE, ["sid1", "sid2"]);}void dispose() {_listener.dispose();}}
room := lksdk.ConnectToRoom(url,info,&lksdk.RoomCallback{OnDataReceived: func(data []byte, rp *lksdk.RemoteParticipant) {// process received data},},)// publish lossy data to the entire roomroom.LocalParticipant.PublishData(data, DataPacket_Kind.LOSSY, nil)// publish reliable data to a set of participantsroom.LocalParticipant.PublishData(data, DataPacket_Kind.RELIABLE, []string{"sid1", "sid2"})
yield return room.LocalParticipant.PublishData(data, DataPacketKind.RELIABLE, participant1, participant2);room.DataReceived += (data, participant, kind) =>{// process received data};