You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
82 lines
2.5 KiB
82 lines
2.5 KiB
1 month ago
|
import { randomString } from '@/lib/client-utils';
|
||
|
import { ConnectionDetails } from '@/lib/types';
|
||
|
import { AccessToken, AccessTokenOptions, VideoGrant } from 'livekit-server-sdk';
|
||
|
import { NextRequest, NextResponse } from 'next/server';
|
||
|
|
||
|
const API_KEY = process.env.LIVEKIT_API_KEY;
|
||
|
const API_SECRET = process.env.LIVEKIT_API_SECRET;
|
||
|
const LIVEKIT_URL = process.env.LIVEKIT_URL;
|
||
|
|
||
|
export async function GET(request: NextRequest) {
|
||
|
try {
|
||
|
// Parse query parameters
|
||
|
const roomName = request.nextUrl.searchParams.get('roomName');
|
||
|
const participantName = request.nextUrl.searchParams.get('participantName');
|
||
|
const metadata = request.nextUrl.searchParams.get('metadata') ?? '';
|
||
|
const region = request.nextUrl.searchParams.get('region');
|
||
|
const livekitServerUrl = region ? getLiveKitURL(region) : LIVEKIT_URL;
|
||
|
if (livekitServerUrl === undefined) {
|
||
|
throw new Error('Invalid region');
|
||
|
}
|
||
|
|
||
|
if (typeof roomName !== 'string') {
|
||
|
return new NextResponse('Missing required query parameter: roomName', { status: 400 });
|
||
|
}
|
||
|
if (participantName === null) {
|
||
|
return new NextResponse('Missing required query parameter: participantName', { status: 400 });
|
||
|
}
|
||
|
|
||
|
// Generate participant token
|
||
|
const participantToken = await createParticipantToken(
|
||
|
{
|
||
|
identity: `${participantName}__${randomString(4)}`,
|
||
|
name: participantName,
|
||
|
metadata,
|
||
|
},
|
||
|
roomName,
|
||
|
);
|
||
|
|
||
|
// Return connection details
|
||
|
const data: ConnectionDetails = {
|
||
|
serverUrl: livekitServerUrl,
|
||
|
roomName: roomName,
|
||
|
participantToken: participantToken,
|
||
|
participantName: participantName,
|
||
|
};
|
||
|
return NextResponse.json(data);
|
||
|
} catch (error) {
|
||
|
if (error instanceof Error) {
|
||
|
return new NextResponse(error.message, { status: 500 });
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function createParticipantToken(userInfo: AccessTokenOptions, roomName: string) {
|
||
|
const at = new AccessToken(API_KEY, API_SECRET, userInfo);
|
||
|
at.ttl = '5m';
|
||
|
const grant: VideoGrant = {
|
||
|
room: roomName,
|
||
|
roomJoin: true,
|
||
|
canPublish: true,
|
||
|
canPublishData: true,
|
||
|
canSubscribe: true,
|
||
|
};
|
||
|
at.addGrant(grant);
|
||
|
return at.toJwt();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get the LiveKit server URL for the given region.
|
||
|
*/
|
||
|
function getLiveKitURL(region: string | null): string {
|
||
|
let targetKey = 'LIVEKIT_URL';
|
||
|
if (region) {
|
||
|
targetKey = `LIVEKIT_URL_${region}`.toUpperCase();
|
||
|
}
|
||
|
const url = process.env[targetKey];
|
||
|
if (!url) {
|
||
|
throw new Error(`${targetKey} is not defined`);
|
||
|
}
|
||
|
return url;
|
||
|
}
|