LiveKit Flutter
The meeting_place_livekit_flutter plugin provides real-time audio and video call rendering for Flutter applications built on the Meeting Place SDK. It bridges the Matrix transport layer to LiveKit media transport with per-participant end-to-end encryption, and integrates with the meeting_place_matrix SDK to enable audio and video calls in Matrix-backed chat sessions.
Core Concepts
- LiveKit: an open-source, scalable Selective Forwarding Unit (SFU) for real-time media transport of audio and video calls.
- WebRTC: an open standard for peer-to-peer multimedia communication over IP networks, enabling audio and video streaming.
- Matrix RTC: a Matrix extension for managing call signalling and end-to-end encryption of real-time media via Matrix rooms.
- End-to-End Encryption (E2EE): per-participant encryption of call media streams using keys distributed by Matrix RTC, ensuring only authorised participants can decrypt media.
Requirements
- Flutter
>=3.24.0. - Dart SDK
>=3.8.0. meeting_place_matrixSDK with aMatrixConfigthat includeslivekitServiceUrlandlivekitSfuUrl.- Vodozemac encryption runtime initialised once in
main()before creating the SDK. See the meeting_place_matrix README for details.
Install Dependency
Package: meeting_place_livekit_flutter
flutter pub add meeting_place_livekit_flutterAlternatively, add the package to your pubspec.yaml file manually:
dependencies:
meeting_place_livekit_flutter: ^<version_number>Then install it:
flutter pub getCheck the latest version on the pub.dev registry or view the source on GitHub.
Usage
Integrate the plugin into MeetingPlaceMatrixSDK.create() to handle audio and video calls. Set up in this order:
import 'package:flutter_vodozemac/flutter_vodozemac.dart' as fvod;
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await fvod.init();
// Continue with app startup
}config: MatrixConfig(
// ... other settings ...
livekitServiceUrl: Uri.parse('https://your-livekit-jwt-service'),
livekitSfuUrl: Uri.parse('wss://your-livekit-sfu'),
)import 'package:flutter/widgets.dart';
import 'package:meeting_place_livekit_flutter/meeting_place_livekit_flutter.dart';
import 'package:meeting_place_matrix/meeting_place_matrix.dart';
final matrixSDK = await MeetingPlaceMatrixSDK.create(
wallet: wallet,
repositoryConfig: repositoryConfig,
config: matrixConfig, // With livekitServiceUrl and livekitSfuUrl
rtcDelegate: FlutterMatrixRTCDelegate(),
roomFactory: (_) => FlutterLiveKitRoom(),
options: MeetingPlaceMatrixSdkOptions(
// ... options
),
);final chatSDK = await MeetingPlaceMatrixChatSDK.initialiseFromChannel(
channel,
coreSDK: matrixSDK,
chatRepository: chatRepository,
);
final chat = await chatSDK.startChatSession();Once set up, audio and video calls within Matrix rooms use Matrix RTC for signalling and LiveKit for media transport, with per-participant end-to-end encryption handled automatically.
For additional usage examples, see the example folder on GitHub.
Classes and Methods
AudioVideoCallView
A StatelessWidget that renders the video track for a call participant. It returns SizedBox.shrink when hasVideo is false, the session is not LiveKit-backed, or the room has no renderable track for the given participantId.
hasVideo must reflect whether participantId currently has an active video track. Pass it from the controller state so the widget rebuilds only when the caller decides, not via an internal stream subscription.
AudioVideoCallView (constructor)
Creates an AudioVideoCallView widget.
Parameters
session
AudioVideoCallSession?
Requirednull when there is no ongoing call.participantId
String
RequiredhasVideo
bool
Requiredkey
Key?
Optionalmirror
bool
Optionaltrue, mirrors the video view for the local camera preview. The view is mirrored only while the front camera is active. Peers are never mirrored. Defaults to false.Example
import 'package:meeting_place_livekit_flutter/meeting_place_livekit_flutter.dart';
@override
Widget build(BuildContext context, WidgetRef ref) {
final session = ref.watch(provider.select((s) => s.session));
final hasVideo = ref.watch(
provider.select(
(s) =>
s.participants
.firstWhereOrNull((p) => p.participantId == participantId)
?.hasVideo ??
false,
),
);
return AudioVideoCallView(
session: session,
participantId: participantId,
hasVideo: hasVideo,
);
}FlutterLiveKitRoom
Concrete LiveKit implementation of LiveKitRoom. Owns all livekit_client types so they do not leak into the SDK layer. Converts LiveKit events and participants into domain objects before publishing them through the interface.
FlutterLiveKitRoom (constructor)
Creates an instance of FlutterLiveKitRoom.
Parameters
logger
MeetingPlaceCoreSDKLogger?
Optionalhardware
Hardware?
OptionalExample
import 'package:meeting_place_livekit_flutter/meeting_place_livekit_flutter.dart';
import 'package:meeting_place_matrix/meeting_place_matrix.dart';
final matrixSDK = await MeetingPlaceMatrixSDK.create(
wallet: wallet,
repositoryConfig: repositoryConfig,
config: matrixConfig,
rtcDelegate: FlutterMatrixRTCDelegate(),
roomFactory: (_) => FlutterLiveKitRoom(),
);Properties
ownParticipantId
String?
Optionalnull when not connected.participants
List<AudioVideoCallParticipant>
Optionalconnect
Connects to the LiveKit SFU at the given URL using the provided access token.
Parameters
url
String
Requiredwss://your-livekit-sfu).token
String
RequiredparticipantIdToDid
Map<String, String>
OptionalonE2EEStateChanged
OnCallE2EEStateChanged?
OptionalonParticipantDisconnected
OnParticipantDisconnected?
OptionalonParticipantsChanged
void Function()?
OptionalExample
import 'package:meeting_place_livekit_flutter/meeting_place_livekit_flutter.dart';
final room = FlutterLiveKitRoom();
await room.connect(
url: 'wss://your-livekit-sfu',
token: livekitAccessToken,
participantIdToDid: {'alice-livekit-id': 'did:example:alice'},
onParticipantsChanged: () => setState(() {}),
onE2EEStateChanged: (participantId, state) {
debugPrint('E2EE state for $participantId: $state');
},
);disconnect
Disconnects from the room and releases all resources.
Parameters
No parameters required.
Example
await room.disconnect();setCameraEnabled
Enables or disables the local camera.
Parameters
enabled
bool
Requiredtrue to enable the camera or false to disable it.Example
// Disable the camera
await room.setCameraEnabled(false);
// Enable the camera
await room.setCameraEnabled(true);setMicrophoneEnabled
Enables or disables the local microphone.
Parameters
enabled
bool
Requiredtrue to enable the microphone or false to mute it.Example
// Mute the microphone
await room.setMicrophoneEnabled(false);setSpeakerphoneEnabled
Routes audio through the loudspeaker (true) or the earpiece (false).
Parameters
enabled
bool
Requiredtrue to route audio through the loudspeaker or false for the earpiece.Example
await room.setSpeakerphoneEnabled(true);switchCamera
Switches between the front and rear camera.
Parameters
No parameters required.
Example
await room.switchCamera();setSharedKey
Sets the shared E2EE key for the call session.
Parameters
key
String
RequiredExample
await room.setSharedKey('<SHARED-E2EE-KEY>');ratchetKey
Ratchets the E2EE key for a specific participant, advancing the key material for forward secrecy.
Parameters
participantId
String
RequiredkeyIndex
int
RequiredExample
await room.ratchetKey('alice-livekit-id', 0);forceRemoteKeyframe
Forces the SFU to emit a fresh keyframe for a participant’s video stream. Useful when a video track becomes undecodable after an E2EE key rotation.
Parameters
participantId
String
RequiredExample
await room.forceRemoteKeyframe('alice-livekit-id');renderableVideoTrackFor
Returns the renderable video track for a participant, or null when the room is not connected, the participant is not found, or they have no active video track.
Parameters
participantId
String
RequiredExample
final track = room.renderableVideoTrackFor('alice-livekit-id');
if (track != null) {
// Render the track
}FlutterMatrixRTCDelegate
Concrete matrix.WebRTCDelegate that bridges Matrix RTC to flutter_webrtc. Lives in the plugin so that the SDK stays pure Dart. Created once per app session and injected into matrix.VoIP at startup via MeetingPlaceMatrixSDK.create().
The keyProvider is set by the call service before a call starts, allowing per-participant E2EE keys distributed by Matrix RTC to flow into the LiveKit FrameCryptor layer.
FlutterMatrixRTCDelegate (constructor)
Creates an instance of FlutterMatrixRTCDelegate. Takes no arguments.
Parameters
No parameters required.
Example
import 'package:meeting_place_livekit_flutter/meeting_place_livekit_flutter.dart';
import 'package:meeting_place_matrix/meeting_place_matrix.dart';
final matrixSDK = await MeetingPlaceMatrixSDK.create(
wallet: wallet,
repositoryConfig: repositoryConfig,
config: matrixConfig,
rtcDelegate: FlutterMatrixRTCDelegate(),
roomFactory: (_) => FlutterLiveKitRoom(),
);updateKeyProvider
Sets the LiveKit KeyProvider that should receive per-participant E2EE keys distributed by Matrix RTC.
Parameters
provider
KeyProvider?
Requirednull to clear the current provider.Example
import 'package:meeting_place_livekit_flutter/meeting_place_livekit_flutter.dart';
final delegate = FlutterMatrixRTCDelegate();
// Set the key provider before starting a call
delegate.updateKeyProvider(myKeyProvider);
// Clear the key provider after the call ends
delegate.updateKeyProvider(null);Glad to hear it! Please tell us how we can improve more.
Sorry to hear that. Please tell us how we can improve.
Thank you for sharing your feedback so we can improve your experience.