recordings()->where('status', 'recording')->first(); if ($active) { return $active; } $recording = Recording::create([ 'owner_ref' => $session->owner_ref, 'session_id' => $session->id, 'status' => 'recording', 'layout' => $layout, 'started_by_ref' => $host->ownerRef(), 'started_at' => now(), ]); AuditLogger::record( $session->owner_ref, 'recording.started', $session->room->organization_id, $host->ownerRef(), Recording::class, $recording->id, ); return $recording; } public function stop(Recording $recording, string $actorRef): Recording { if ($recording->status !== 'recording') { return $recording; } $recording->update([ 'status' => 'processing', 'ended_at' => now(), 'duration_seconds' => $recording->started_at ? (int) $recording->started_at->diffInSeconds(now()) : null, ]); AuditLogger::record( $recording->owner_ref, 'recording.stopped', $recording->session->room->organization_id, $actorRef, Recording::class, $recording->id, ); ProcessRecording::dispatch($recording->id); return $recording->fresh(); } public function process(Recording $recording): Recording { $session = $recording->session; $filename = 'recordings/'.$session->uuid.'/'.$recording->uuid.'.mp4'; $disk = Storage::disk(config('meet.recordings.disk', 'local')); // Placeholder until LiveKit Egress writes the file; create empty marker for dev. if (! $disk->exists($filename)) { $disk->put($filename, ''); } $recording->update([ 'status' => 'ready', 'storage_path' => $filename, 'file_size' => $disk->size($filename) ?: null, 'thumbnail_path' => null, ]); AuditLogger::record( $recording->owner_ref, 'recording.ready', $session->room->organization_id, null, Recording::class, $recording->id, ); app(MeetNotificationService::class)->recordingReady($recording); app(\App\Services\Integrations\WebhookDispatcher::class)->recordingReady($recording); app(MeetBillingService::class)->chargeRecordingStorageInitial($recording->fresh()); if ($session->room->setting('auto_ai_summary', false) || config('meet.ai.auto_summarize', true)) { app(TranscriptService::class)->ensureForSession($session, $recording); } return $recording->fresh(); } public function delete(Recording $recording, string $actorRef): void { if ($recording->storage_path) { Storage::disk(config('meet.recordings.disk', 'local'))->delete($recording->storage_path); } AuditLogger::record( $recording->owner_ref, 'recording.deleted', $recording->session->room->organization_id, $actorRef, Recording::class, $recording->id, ); $recording->delete(); } }