Files
ladill-meet/app/Http/Controllers/Api/LiveKitWebhookController.php
T
isaaccladandCursor 4e4bed0df3
Deploy Ladill Meet / deploy (push) Successful in 52s
Record meetings with LiveKit Egress instead of browser capture.
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>
2026-07-04 03:18:28 +00:00

58 lines
1.7 KiB
PHP

<?php
namespace App\Http\Controllers\Api;
use Agence104\LiveKit\WebhookReceiver;
use App\Http\Controllers\Controller;
use App\Models\Recording;
use App\Services\Meet\RecordingService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
class LiveKitWebhookController extends Controller
{
public function __invoke(Request $request, RecordingService $recordings): JsonResponse
{
try {
$receiver = new WebhookReceiver(
(string) config('meet.media.livekit.api_key'),
(string) config('meet.media.livekit.api_secret'),
);
$event = $receiver->receive(
$request->getContent(),
$request->header('Authorization'),
);
} catch (\Throwable $e) {
Log::warning('LiveKit webhook rejected.', ['error' => $e->getMessage()]);
return response()->json(['error' => 'invalid webhook'], 401);
}
if ($event->getEvent() !== 'egress_ended' || ! $event->hasEgressInfo()) {
return response()->json(['status' => 'ignored']);
}
$info = $event->getEgressInfo();
$egressId = $info->getEgressId();
if ($egressId === '') {
return response()->json(['status' => 'ignored']);
}
$recording = Recording::query()
->whereIn('status', ['recording', 'processing'])
->where('metadata->egress_id', $egressId)
->first();
if (! $recording) {
return response()->json(['status' => 'not_found']);
}
$recordings->completeFromEgress($recording, $info);
return response()->json(['status' => 'accepted']);
}
}