Record meetings with LiveKit Egress instead of browser capture.
Deploy Ladill Meet / deploy (push) Successful in 52s
Deploy Ladill Meet / deploy (push) Successful in 52s
Server-side room composite egress replaces fragile MediaRecorder DOM capture when enabled, with webhook completion and browser fallback when egress is unavailable. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -67,6 +67,8 @@ function readMeetRoomBootState() {
|
||||
videoOffOnJoin: el.dataset.videoOffOnJoin === '1' || audioOnly,
|
||||
isRecording: el.dataset.recordingActive === '1',
|
||||
activeRecordingUuid: el.dataset.activeRecordingUuid || null,
|
||||
recordingCaptureMode: el.dataset.captureMode || null,
|
||||
serverEgress: el.dataset.serverEgress === '1',
|
||||
isLocked: el.dataset.locked === '1',
|
||||
watermark: el.dataset.watermark === '1',
|
||||
liveCaptions: el.dataset.liveCaptions === '1',
|
||||
@@ -139,6 +141,8 @@ function meetRoom() {
|
||||
inBreakout: roomBoot.inBreakout ?? false,
|
||||
assignedBreakoutRoomId: roomBoot.assignedBreakoutRoomId ?? null,
|
||||
activeRecordingUuid: roomBoot.activeRecordingUuid ?? null,
|
||||
recordingCaptureMode: roomBoot.recordingCaptureMode ?? null,
|
||||
serverEgress: roomBoot.serverEgress ?? false,
|
||||
sessionParticipants: roomBoot.sessionParticipants ?? [],
|
||||
roomHost: roomBoot.roomHost ?? null,
|
||||
captionText: '',
|
||||
@@ -250,6 +254,8 @@ function meetRoom() {
|
||||
this.videoOffOnJoin = el.dataset.videoOffOnJoin === '1' || this.audioOnly;
|
||||
this.isRecording = el.dataset.recordingActive === '1';
|
||||
this.activeRecordingUuid = el.dataset.activeRecordingUuid || null;
|
||||
this.recordingCaptureMode = el.dataset.captureMode || null;
|
||||
this.serverEgress = el.dataset.serverEgress === '1';
|
||||
this.isLocked = el.dataset.locked === '1';
|
||||
this.watermark = el.dataset.watermark === '1';
|
||||
this.liveCaptions = el.dataset.liveCaptions === '1';
|
||||
@@ -1725,11 +1731,19 @@ function meetRoom() {
|
||||
}
|
||||
},
|
||||
|
||||
usesServerEgressCapture() {
|
||||
return this.recordingCaptureMode === 'egress';
|
||||
},
|
||||
|
||||
async maybeStartAutoRecording() {
|
||||
if (!this.isHost || !this.isRecording || recordingMediaRecorder) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.usesServerEgressCapture()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const el = document.getElementById('meet-config');
|
||||
const existingUuid = this.activeRecordingUuid || el?.dataset.activeRecordingUuid || '';
|
||||
|
||||
@@ -1772,10 +1786,18 @@ function meetRoom() {
|
||||
|
||||
const data = await res.json();
|
||||
this.activeRecordingUuid = data.recording_uuid;
|
||||
this.recordingCaptureMode = data.capture_mode || 'browser';
|
||||
|
||||
if (this.usesServerEgressCapture()) {
|
||||
this.isRecording = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (! await this.tryStartClientRecordingWithRetry()) {
|
||||
await this.abortServerRecording('Could not capture meeting video in this browser.');
|
||||
this.isRecording = false;
|
||||
this.activeRecordingUuid = null;
|
||||
this.recordingCaptureMode = null;
|
||||
window.alert(`Recording could not start because this browser could not capture the ${this.sessionNoun()} video. Try Chrome on desktop, or disable stage-only layouts temporarily.`);
|
||||
return;
|
||||
}
|
||||
@@ -1876,8 +1898,9 @@ function meetRoom() {
|
||||
},
|
||||
|
||||
async stopServerAndUploadRecording() {
|
||||
const isServerEgress = this.usesServerEgressCapture();
|
||||
const hadClientRecorder = !!recordingMediaRecorder;
|
||||
const blob = await this.stopClientRecording();
|
||||
const blob = isServerEgress ? null : await this.stopClientRecording();
|
||||
this.isRecording = false;
|
||||
|
||||
let recordingUuid = this.activeRecordingUuid;
|
||||
@@ -1885,8 +1908,18 @@ function meetRoom() {
|
||||
if (res.ok) {
|
||||
const data = await res.json().catch(() => ({}));
|
||||
recordingUuid = data.recording_uuid || recordingUuid;
|
||||
if (data.capture_mode) {
|
||||
this.recordingCaptureMode = data.capture_mode;
|
||||
}
|
||||
} else if (res.status !== 404 || !recordingUuid) {
|
||||
this.activeRecordingUuid = null;
|
||||
this.recordingCaptureMode = null;
|
||||
return;
|
||||
}
|
||||
|
||||
if (isServerEgress) {
|
||||
this.activeRecordingUuid = null;
|
||||
this.recordingCaptureMode = null;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1908,6 +1941,7 @@ function meetRoom() {
|
||||
}
|
||||
|
||||
this.activeRecordingUuid = null;
|
||||
this.recordingCaptureMode = null;
|
||||
},
|
||||
|
||||
async abortServerRecording(reason) {
|
||||
|
||||
@@ -107,6 +107,8 @@
|
||||
data-locked="{{ $session->is_locked ? '1' : '0' }}"
|
||||
data-recording-active="{{ $activeRecording ? '1' : '0' }}"
|
||||
data-active-recording-uuid="{{ $activeRecording?->uuid ?? '' }}"
|
||||
data-capture-mode="{{ $activeRecording?->metadata['capture_mode'] ?? '' }}"
|
||||
data-server-egress="{{ ($serverEgressAvailable ?? false) ? '1' : '0' }}"
|
||||
data-is-webinar="{{ ($isWebinar ?? false) ? '1' : '0' }}"
|
||||
data-is-conference="{{ ($isConference ?? false) ? '1' : '0' }}"
|
||||
data-session-noun="{{ $sessionNoun }}"
|
||||
|
||||
Reference in New Issue
Block a user