openvidu-recording-improved: Improve recording status update system

This commit is contained in:
juancarmore 2024-09-09 21:07:34 +02:00
parent 685f4bed8b
commit 1095fc6b84
3 changed files with 101 additions and 41 deletions

View File

@ -42,8 +42,9 @@ async function joinRoom() {
});
// When recording status changes...
room.on(LivekitClient.RoomEvent.RecordingStatusChanged, async (isRecording) => {
await updateRecordingInfo(isRecording);
room.on(LivekitClient.RoomEvent.RoomMetadataChanged, async (metadata) => {
const { recordingStatus } = JSON.parse(metadata);
await updateRecordingInfo(recordingStatus);
});
try {
@ -68,7 +69,13 @@ async function joinRoom() {
addTrack(localVideoTrack, userName, true);
// Update recording info
await updateRecordingInfo(room.isRecording);
const { recordingStatus } = JSON.parse(room.metadata);
await updateRecordingInfo(recordingStatus);
if (recordingStatus !== "STOPPED" && recordingStatus !== "FAILED") {
const roomId = await room.getSid();
await listRecordings(room.name, roomId);
}
} catch (error) {
console.log("There was an error connecting to the room:", error.message);
await leaveRoom();
@ -200,49 +207,47 @@ async function getToken(roomName, participantName) {
return body.token;
}
async function updateRecordingInfo(isRecording) {
async function updateRecordingInfo(recordingStatus) {
const recordingButton = document.getElementById("recording-button");
const recordingText = document.getElementById("recording-text");
if (isRecording) {
recordingButton.disabled = false;
recordingButton.innerText = "Stop Recording";
recordingButton.className = "btn btn-danger";
recordingText.hidden = false;
} else {
recordingButton.disabled = false;
recordingButton.innerText = "Start Recording";
recordingButton.className = "btn btn-primary";
recordingText.hidden = true;
}
switch (recordingStatus) {
case "STARTING":
recordingButton.disabled = true;
recordingButton.innerText = "Starting...";
break;
case "STARTED":
recordingButton.disabled = false;
recordingButton.innerText = "Stop Recording";
recordingButton.className = "btn btn-danger";
recordingText.hidden = false;
break;
case "STOPPING":
recordingButton.disabled = true;
recordingButton.innerText = "Stopping...";
recordingButton.className = "btn btn-danger";
recordingText.hidden = false;
break;
case "STOPPED":
case "FAILED":
recordingButton.disabled = false;
recordingButton.innerText = "Start Recording";
recordingButton.className = "btn btn-primary";
recordingText.hidden = true;
const roomId = await room.getSid();
await listRecordings(room.name, roomId);
const roomId = await room.getSid();
await listRecordings(room.name, roomId);
break;
}
}
async function manageRecording() {
const recordingButton = document.getElementById("recording-button");
if (recordingButton.innerText === "Start Recording") {
recordingButton.disabled = true;
recordingButton.innerText = "Starting...";
const [error, _] = await startRecording();
if (error && error.status !== 409) {
recordingButton.disabled = false;
recordingButton.innerText = "Start Recording";
}
await startRecording();
} else {
recordingButton.disabled = true;
recordingButton.innerText = "Stopping...";
const [error, _] = await stopRecording();
if (error && error.status !== 409) {
recordingButton.disabled = false;
recordingButton.innerText = "Stop Recording";
}
await stopRecording();
}
}

View File

@ -1,10 +1,11 @@
import express, { Router } from "express";
import { WebhookReceiver } from "livekit-server-sdk";
import { LIVEKIT_API_KEY, LIVEKIT_API_SECRET } from "../config.js";
import { EgressStatus, RoomServiceClient, WebhookReceiver } from "livekit-server-sdk";
import { LIVEKIT_URL, LIVEKIT_API_KEY, LIVEKIT_API_SECRET } from "../config.js";
import { S3Service } from "../services/s3.service.js";
const webhookReceiver = new WebhookReceiver(LIVEKIT_API_KEY, LIVEKIT_API_SECRET);
const s3Service = new S3Service();
const roomClient = new RoomServiceClient(LIVEKIT_URL, LIVEKIT_API_KEY, LIVEKIT_API_SECRET);
export const webhookController = Router();
webhookController.use(express.raw({ type: "application/webhook+json" }));
@ -31,7 +32,7 @@ webhookController.post("/", async (req, res) => {
});
const handleEgressUpdated = async (egressInfo) => {
await updateRecordingStatus(egressInfo);
};
const handleEgressEnded = async (egressInfo) => {
@ -39,6 +40,8 @@ const handleEgressEnded = async (egressInfo) => {
const metadataName = recordingInfo.name.replace(".mp4", ".json");
const key = `recordings/.metadata/${metadataName}`;
await s3Service.uploadObject(key, recordingInfo);
await updateRecordingStatus(egressInfo);
};
const convertToRecordingInfo = (egressInfo) => {
@ -50,3 +53,30 @@ const convertToRecordingInfo = (egressInfo) => {
size: Number(file.size)
};
};
const updateRecordingStatus = async (egressInfo) => {
const roomName = egressInfo.roomName;
const recordingStatus = getRecordingStatus(egressInfo.status);
await roomClient.updateRoomMetadata(
roomName,
JSON.stringify({
createdBy: "openvidu-recording-improved-tutorial",
recordingStatus
})
);
};
const getRecordingStatus = (egressStatus) => {
switch (egressStatus) {
case EgressStatus.EGRESS_STARTING:
return "STARTING";
case EgressStatus.EGRESS_ACTIVE:
return "STARTED";
case EgressStatus.EGRESS_ENDING:
return "STOPPING";
case EgressStatus.EGRESS_COMPLETE:
return "STOPPED";
default:
return "FAILED";
}
};

View File

@ -3,8 +3,8 @@ import express from "express";
import cors from "cors";
import path from "path";
import { fileURLToPath } from "url";
import { AccessToken } from "livekit-server-sdk";
import { LIVEKIT_API_KEY, LIVEKIT_API_SECRET, SERVER_PORT } from "./config.js";
import { AccessToken, RoomServiceClient } from "livekit-server-sdk";
import { LIVEKIT_URL, LIVEKIT_API_KEY, LIVEKIT_API_SECRET, SERVER_PORT } from "./config.js";
import { recordingController } from "./controllers/recording.controller.js";
import { webhookController } from "./controllers/webhook.controller.js";
@ -33,8 +33,33 @@ app.post("/token", async (req, res) => {
const at = new AccessToken(LIVEKIT_API_KEY, LIVEKIT_API_SECRET, {
identity: participantName
});
at.addGrant({ roomJoin: true, room: roomName, roomRecord: true });
const permissions = {
room: roomName,
roomJoin: true,
roomAdmin: true,
roomList: true,
roomRecord: true
};
at.addGrant(permissions);
const token = await at.toJwt();
const roomClient = new RoomServiceClient(LIVEKIT_URL, LIVEKIT_API_KEY, LIVEKIT_API_SECRET);
// Check if room already exists
const rooms = await roomClient.listRooms([roomName]);
// Create room if it doesn't exist
if (rooms.length === 0) {
const roomOptions = {
name: roomName,
metadata: JSON.stringify({
createdBy: "openvidu-recording-improved-tutorial",
recordingStatus: "STOPPED"
})
};
await roomClient.createRoom(roomOptions);
}
res.json({ token });
});