Deploy Ladill Meet / deploy (push) Successful in 51s
Create rooms via the LiveKit API, retry egress when the room is missing, and resume server egress after the host connects when auto-record fell back to browser capture. Co-authored-by: Cursor <cursoragent@cursor.com>
116 lines
3.4 KiB
PHP
116 lines
3.4 KiB
PHP
<?php
|
|
|
|
namespace App\Services\Meet\Media;
|
|
|
|
use Agence104\LiveKit\AccessToken;
|
|
use Agence104\LiveKit\AccessTokenOptions;
|
|
use Agence104\LiveKit\RoomCreateOptions;
|
|
use Agence104\LiveKit\RoomServiceClient;
|
|
use Agence104\LiveKit\VideoGrant;
|
|
use Illuminate\Support\Facades\Log;
|
|
|
|
class LiveKitProvider implements MediaProviderInterface
|
|
{
|
|
public function createRoom(string $roomName, array $options = []): void
|
|
{
|
|
if (! $this->isConfigured()) {
|
|
return;
|
|
}
|
|
|
|
try {
|
|
$client = new RoomServiceClient(
|
|
$this->apiHost(),
|
|
(string) config('meet.media.livekit.api_key'),
|
|
(string) config('meet.media.livekit.api_secret'),
|
|
);
|
|
|
|
$client->createRoom(new RoomCreateOptions([
|
|
'name' => $roomName,
|
|
'empty_timeout' => (int) ($options['empty_timeout'] ?? 300),
|
|
]));
|
|
} catch (\Throwable $e) {
|
|
Log::warning('LiveKit createRoom failed.', [
|
|
'room' => $roomName,
|
|
'error' => $e->getMessage(),
|
|
]);
|
|
}
|
|
}
|
|
|
|
public function deleteRoom(string $roomName): void
|
|
{
|
|
if (! $this->isConfigured() || $roomName === '') {
|
|
return;
|
|
}
|
|
|
|
try {
|
|
$client = new RoomServiceClient(
|
|
$this->apiHost(),
|
|
(string) config('meet.media.livekit.api_key'),
|
|
(string) config('meet.media.livekit.api_secret'),
|
|
);
|
|
|
|
$client->deleteRoom($roomName);
|
|
} catch (\Throwable $e) {
|
|
Log::warning('LiveKit deleteRoom failed.', [
|
|
'room' => $roomName,
|
|
'error' => $e->getMessage(),
|
|
]);
|
|
}
|
|
}
|
|
|
|
public function generateToken(
|
|
string $roomName,
|
|
string $identity,
|
|
string $displayName,
|
|
array $grants = [],
|
|
): string {
|
|
$apiKey = (string) config('meet.media.livekit.api_key');
|
|
$apiSecret = (string) config('meet.media.livekit.api_secret');
|
|
|
|
$tokenOptions = (new AccessTokenOptions())
|
|
->setIdentity($identity)
|
|
->setName($displayName)
|
|
->setTtl(3600);
|
|
|
|
$videoGrant = (new VideoGrant())
|
|
->setRoomJoin()
|
|
->setRoomName($roomName)
|
|
->setCanPublish($grants['can_publish'] ?? true)
|
|
->setCanSubscribe($grants['can_subscribe'] ?? true)
|
|
->setCanPublishData($grants['can_publish_data'] ?? true);
|
|
|
|
if ($grants['room_admin'] ?? false) {
|
|
$videoGrant->setRoomAdmin();
|
|
}
|
|
|
|
return (new AccessToken($apiKey, $apiSecret))
|
|
->init($tokenOptions)
|
|
->setGrant($videoGrant)
|
|
->toJwt();
|
|
}
|
|
|
|
public function isConfigured(): bool
|
|
{
|
|
return filled(config('meet.media.livekit.url'))
|
|
&& filled(config('meet.media.livekit.api_key'))
|
|
&& filled(config('meet.media.livekit.api_secret'));
|
|
}
|
|
|
|
public function serverUrl(): string
|
|
{
|
|
return (string) config('meet.media.livekit.url');
|
|
}
|
|
|
|
public function apiHost(): string
|
|
{
|
|
$override = (string) config('meet.media.livekit.api_url', '');
|
|
if ($override !== '') {
|
|
return rtrim($override, '/');
|
|
}
|
|
|
|
$url = (string) config('meet.media.livekit.url', '');
|
|
|
|
return (string) preg_replace('#^wss:#', 'https:', (string) preg_replace('#^ws:#', 'http:', $url));
|
|
}
|
|
}
|