* WIP add recording support * Add region env var * Add recording indicator * Indicator and support for stopping recording * remove logs * rename server functions
77 lines
2.0 KiB
TypeScript
77 lines
2.0 KiB
TypeScript
import { EgressClient, EncodedFileOutput, S3Upload } from 'livekit-server-sdk';
|
|
import { NextApiRequest, NextApiResponse } from 'next';
|
|
|
|
export default async function startRecording(req: NextApiRequest, res: NextApiResponse) {
|
|
try {
|
|
const { roomName } = req.query;
|
|
|
|
/**
|
|
* CAUTION:
|
|
* for simplicity this implementation does not authenticate users and therefore allows anyone with knowledge of a roomName
|
|
* to start/stop recordings for that room.
|
|
* DO NOT USE THIS FOR PRODUCTION PURPOSES AS IS
|
|
*/
|
|
|
|
if (typeof roomName !== 'string') {
|
|
res.statusMessage = 'Missing roomName parameter';
|
|
res.status(403).end();
|
|
return;
|
|
}
|
|
|
|
const {
|
|
LIVEKIT_API_KEY,
|
|
LIVEKIT_API_SECRET,
|
|
LIVEKIT_URL,
|
|
S3_KEY_ID,
|
|
S3_KEY_SECRET,
|
|
S3_BUCKET,
|
|
S3_ENDPOINT,
|
|
S3_REGION,
|
|
} = process.env;
|
|
|
|
const hostURL = new URL(LIVEKIT_URL!);
|
|
hostURL.protocol = 'https:';
|
|
|
|
const egressClient = new EgressClient(hostURL.origin, LIVEKIT_API_KEY, LIVEKIT_API_SECRET);
|
|
|
|
const existingEgresses = await egressClient.listEgress({ roomName });
|
|
if (existingEgresses.length > 0 && existingEgresses.some((e) => e.status < 2)) {
|
|
(res.statusMessage = 'Meeting is already being recorded'), res.status(409).end();
|
|
return;
|
|
}
|
|
|
|
const fileOutput = new EncodedFileOutput({
|
|
filepath: `${new Date(Date.now()).toISOString()}-${roomName}.mp4`,
|
|
output: {
|
|
case: 's3',
|
|
value: new S3Upload({
|
|
endpoint: S3_ENDPOINT,
|
|
accessKey: S3_KEY_ID,
|
|
secret: S3_KEY_SECRET,
|
|
region: S3_REGION,
|
|
bucket: S3_BUCKET,
|
|
}),
|
|
},
|
|
});
|
|
|
|
await egressClient.startRoomCompositeEgress(
|
|
roomName,
|
|
{
|
|
file: fileOutput,
|
|
},
|
|
{
|
|
layout: 'speaker',
|
|
},
|
|
);
|
|
|
|
res.status(200).end();
|
|
} catch (e) {
|
|
if (e instanceof Error) {
|
|
res.statusMessage = e.name;
|
|
console.error(e);
|
|
res.status(500).end();
|
|
return;
|
|
}
|
|
}
|
|
}
|