hi i am using livekit in my app Below is the funct...
# egress
b
hi i am using livekit in my app Below is the functionality of app Host having n number of user I want to record call on user side on user side i want recording of host and the logged in user not all user below is my code i am using 2.15.0 sdk version on nodejs
Copy code
onst startRecording = async (req, res) => { console.log("========== START RECORDING API CALLED =========="); console.log("Request Body:", req.body); console.log("Auth Type:", req.authType); console.log("User ID:", req.userId); console.log("Host ID:", req.hostId); console.log("Login ID:", req.login_id); try { const role = req.authType; console.log("Role Detected:", role); console.log("Fetching AWS Config..."); const config = await getAWSConfig(); console.log("AWS Config Loaded:", { livekitHost: config.livekitHost, apiKey: config.livekitApiKey ? "Present" : "Missing", bucket: config.bucket, region: config.region, }); console.log("Creating Egress Client..."); const egressClient = new EgressClient( config.livekitHost.replace("wss://", "https://"), config.livekitApiKey, config.livekitSecret ); console.log("Egress Client Created Successfully"); let hostId; let participantsToRecord = []; console.log("Checking Role Logic..."); if (role === 4) { console.log("Role is HOST (4)"); hostId = req.userId?.toString(); participantsToRecord = [host_${hostId}]; console.log("Host Participants:", participantsToRecord); } else if (role === 6) { console.log("Role is USER (6)"); hostId = req.hostId?.toString(); const userIdentity = req.login_id; const hostIdentity = "roothost"; participantsToRecord = [hostIdentity, userIdentity]; console.log("User Participants:", participantsToRecord); } else { console.log("Unauthorized Role:", role); return res.status(403).json({ success: false, message: "Recording not allowed for this role", }); } const roomName = call_${hostId}; console.log("Room Name:", roomName); console.log("Checking if recording already exists..."); console.log("Active Recordings Store:", activeRecordings.host); // Make sure the per-host store exists activeRecordings.host[hostId] = activeRecordings.host[hostId] || {}; // Now check per-user if (activeRecordings.host[hostId][req.userId?.toString()]) { console.log("Recording already running for user:", req.userId); return res.status(400).json({ success: false, message: "Recording already running for this user", }); } let filePath; if (role === 4) { filePath = recordings/host/${hostId}/${uuidv4()}.mp4; console.log("Host Recording Path:", filePath); } else { const userId = req.userId.toString(); filePath = recordings/user/${hostId}/${userId}_${uuidv4()}.mp4; console.log("User Recording Path:", filePath); } console.log("Preparing S3 File Output..."); const fileOutput = new DirectFileOutput({ filepath: filePath, // filepath: recordings/composite_${uuidv4()}.ogg, output: { case: "s3", value: new S3Upload({ accessKey: config.accessKey, secret: config.secret, bucket: config.bucket, region: config.region, }), }, }); console.log("Starting Room Composite Egress..."); console.log("Egress Options:", { layout: "grid", audioOnly: false, participants: participantsToRecord, }); const requestedUsers = [req.login_id,"roothost"]; // ["101", "204"] const audioTrackIds = []; const roomService = await getRoomService(); const participants = await roomService.listParticipants(roomName); for (const p of participants) { if (!requestedUsers.includes(p.identity)) continue; for (const pub of p.tracks) { console.log(pub,"pub") // MICROPHONE audio track // if (pub.source === 1 && pub.sid && !pub.muted) { audioTrackIds.push(pub.sid); // } } } console.log("Collected Audio Track IDs:", audioTrackIds); const egressRequest = { roomName, // include roomName here audioTrackIds, // array of strings file: fileOutput, // S3 or local output layout: "grid" // optional for video }; // const egress = await egressClient.startRoomCompositeEgress( // roomName, // fileOutput, // { // layout: "grid", // audioOnly: true, // audioTrackSelector: { // participants: requestedUsers // participant identities, NOT track SIDs // } // } // ); const egress = await egressClient.startTrackCompositeEgress(roomName, { audioTrackIds: [audioTrackIds], // only this user's track file: fileOutput }); console.log("Track composite egress started:", egress.egressId); // Ensure egressId exists before storing if (!egress?.egressId) { // wait for egress to be fully initialized if SDK provides an event await new Promise((resolve, reject) => { egressClient.once('egress_started', (event) => { if (event.egressId) { resolve(event.egressId); } else { reject(new Error("Egress started but egressId not found")); } }); // Optional: add timeout to reject after 10s setTimeout(() => reject(new Error("Egress start timed out")), 10000); }).then((id) => { egress.egressId = id; }); } console.log("✅ TRACK EGRESS STARTED:", egress.egressId); console.log("✅ EGRESS STARTED SUCCESSFULLY"); console.log("Egress ID:", egress.egressId); // activeRecordings.host[hostId] = egress.egressId; // Store egressId per host AND per user activeRecordings.host[hostId] = activeRecordings.host[hostId] || {}; activeRecordings.host[hostId][req.userId.toString()] = egress.egressId; console.log("Active Recording Updated:", activeRecordings.host); console.log("========== START RECORDING SUCCESS =========="); return res.json({ success: true, message: "Recording started", egressId: egress.egressId, filePath, }); } catch (error) { console.error("========== START RECORDING ERROR =========="); console.error("Error Message:", error.message); console.error("Stack:", error.stack); return res.status(500).json({ success: false, message: error.message, }); } };
Any update on this Team ?