Daravelv1.13.0
ENID GitHub

LiveKit

LiveKit membawa video, audio, dan berbagi layar sebuah kelas virtual atau rapat lewat WebRTC; browser atau aplikasi Flutter terhubung ke sana dengan livekit_client. daravel_livekit adalah sisi server-nya: menandatangani access token yang dipakai client untuk terhubung, mengelola room dan participant lewat room service LiveKit, serta memverifikasi webhook dari LiveKit. Paket ini berbicara protokol yang sama dengan SDK PHP LiveKit (agence104/livekit-server-sdk), sehingga aplikasi Laravel dan Daravel bisa berbagi satu server LiveKit.

dart pub add daravel_livekit
// bootstrap/app.dart
import 'package:daravel_livekit/daravel_livekit.dart';

Application createApp() => Application.configure(basePath: basePath)
    .withLivekit()
    // ...
    .create();
LIVEKIT_URL=https://livekit.example.com   # atau LIVEKIT_HOST, nama lama di aplikasi lama
LIVEKIT_API_KEY=...
LIVEKIT_API_SECRET=...                    # atau LIVEKIT_SECRET_KEY

Boot memberi peringatan selama key atau secret belum diisi.

Token#

Client bergabung ke room dengan token yang ditandatangani server:

router.post('/classes/{id}/join', (request) async {
  final user = (await Auth.user<User>())!;
  final token = await Livekit.token(
    identity: user.uuid,
    name: user.name,
    ttl: const Duration(hours: 2),
    video: VideoGrant(roomJoin: true, room: 'class-7a', roomAdmin: user.isTeacher),
  ).toJwt();
  return {'token': token, 'url': Livekit.config.url};
});

VideoGrant memakai field dari LiveKit (roomJoin, room, roomAdmin, canPublish, canSubscribe, canPublishData, canPublishSources, hidden, ...); field yang tidak diisi tidak dikirim, sehingga default LiveKit yang berlaku. Bergabung ke room membutuhkan identity, dan token berlaku 4 jam kecuali ttl menentukan lain. LivekitToken.verify(jwt, apiKey: ..., apiSecret: ...) membacanya kembali.

Room dan participant#

final rooms = Livekit.rooms;

if ((await rooms.listRooms(['class-7a'])).isEmpty) {
  await rooms.createRoom('class-7a', maxParticipants: 40, metadata: '{"subject":"math"}');
}
final present = await rooms.listParticipants('class-7a');
await rooms.updateParticipant('class-7a', 'student-9', metadata: '{"hand":true}');
await rooms.removeParticipant('class-7a', 'student-9');
await rooms.sendData('class-7a', utf8.encode('{"type":"quiz"}'), topic: 'lk-chat');
await rooms.deleteRoom('class-7a');

Setiap pemanggilan ditandatangani dengan token 10 menit yang hanya membawa grant yang dibutuhkannya (roomCreate, roomList, atau roomAdmin pada room itu), seperti SDK LiveKit. Penolakan berupa LivekitException dengan code dari Twirp (not_found, permission_denied) dan status HTTP-nya. Client mengirim lewat HTTP client aplikasi, sehingga Http.fake() bisa menggantikannya di test.

Webhook#

LiveKit mengirim event (room_started, room_finished, participant_joined, participant_left, track_published, egress_ended, ...) yang ditandatangani dengan API secret:

router.post('/livekit/webhook', (request) async {
  final event = await Livekit.webhook(request);
  if (event.event == 'room_finished') {
    await Meeting.query().where('livekit_room_name', event.room!.name).update({'status': 'FINISHED'});
  }
  return Response.noContent();
});

Livekit.webhook mengecek token di Authorization (signature, masa berlaku, diterbitkan atas API key) dan bahwa klaim sha256-nya adalah SHA-256 base64 dari body yang persis sama, seperti SDK LiveKit; selain itu dijawab 401 dengan LivekitWebhookException. Tidak ada opsi untuk melewati pengecekan itu: route webhook yang menerima event tanpa tanda tangan membuat siapa pun bisa menandai sebuah rapat sudah selesai.

Bersama Laravel#

bench/interop/livekit.sh menjalankan SDK PHP LiveKit dan Daravel saling berhadapan: masing-masing memverifikasi token dari sisi lain, serta menerima webhook bertanda tangan dari sisi lain dan menolak body yang diubah. Test berjalan terhadap server LiveKit dalam mode development, yang menerima join token dari Daravel. Egress dan ingress, serta grant SIP, belum dicakup.