colossal-article-77548
08/11/2025, 11:42 AMtall-airline-16756
08/11/2025, 11:42 AMtall-airline-16756
08/11/2025, 11:43 AMimport { RoomServiceClient } from 'livekit-server-sdk';
// Initialize RoomServiceClient
const roomService = new RoomServiceClient(LIVEKIT_URL, API_KEY, API_SECRET);
// API endpoint to pin a participant
export async function POST(request) {
try {
const { roomName, identity } = await request.json();
if (!roomName || !identity) {
return new NextResponse("Missing required parameters", { status: 400 });
}
// Update participant's attributes to indicate they are pinned
const updateResponse = await roomService.updateParticipant(roomName, identity, {
attributes: { isPinned: 'true' }
});
return NextResponse.json(updateResponse);
} catch (error) {
return handleError(error);
}
}
2. Client-Side Implementation (React)
Then, on the client side, keep track of pinned participants and update the video display like this:
import { useEffect, useState } from 'react';
import { RoomServiceClient } from 'livekit-server-sdk';
// Assuming you have a LiveKit room client connected
const [pinnedParticipants, setPinnedParticipants] = useState(new Set());
// Fetch pinned participants from your backend
const fetchPinnedParticipants = async () => {
const response = await fetch('/api/get-pinned-participants');
const data = await response.json();
setPinnedParticipants(new Set(data));
};
// When a participant is pinned, update their attributes
const pinParticipant = async (roomName, identity) => {
await fetch(`/api/pin-participant`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ roomName, identity }),
});
};
// In your LiveKit room component, prioritize pinned participants
useEffect(() => {
const handleParticipantConnected = (participant) => {
// Check if the participant is pinned
const isPinned = participant.attributes?.isPinned === 'true';
if (isPinned) {
// Set this participant as active or give them priority
setVideoPriority(participant, 'high');
}
};
// Listen for metadata changes which may indicate pinning
room.on('participantMetadataChanged', (participant) => {
const isPinned = participant.attributes?.isPinned === 'true';
if (isPinned) {
setVideoPriority(participant, 'high');
}
});
}, [room]);
Quick Explanation
• Server-Side Update: Your server endpoint updates the participant’s attributes by setting isPinned: 'true'
. This update is then shared with all clients through LiveKit events.
• Client-Side Handling: Your React app listens for participant events. When someone is pinned, it bumps up their video priority to ‘high’, so their video stands out.
By using custom attributes like this, you can easily manage the pinning state and make sure everyone sees the pinned participant front and center. Hope this helps you build a smooth and interactive experience!
Sources: protobufs/livekit_sip.proto | quickstart/src/joinroom.js | agent-console/app/api/room/update-participant/route.ts | packages/livekit-server-sdk/src/RoomServiceClient.ts