Skip to main content

Flutter SDK

TgoRTC Flutter SDK for cross-platform audio/video communication based on LiveKit.

Installation

Latest version:

Add the dependency in pubspec.yaml:

dependencies:
tgortcflutter: ^1.0.0

Dependencies

The SDK automatically includes:

  • livekit_client: ^2.3.6
  • flutter_webrtc: ^0.12.12

Common Entry Points

TgoRTC.instance.roomManager
TgoRTC.instance.participantManager
TgoRTC.instance.audioManager

Quick Start

1. Initialize SDK

import 'package:tgortcflutter/tgortc.dart';

TgoRTC.instance.init(
Options()
..debug = true
..mirror = false,
);

2. Create Room Info and Join

import 'package:tgortcflutter/entity/const.dart';
import 'package:tgortcflutter/entity/room_info.dart';

final roomInfo = RoomInfo(
'roomName',
'token',
'url',
'loginUID',
'creatorUID',
);

roomInfo.maxParticipants = 9;
roomInfo.rtcType = RTCType.video;
roomInfo.timeout = 30;

await TgoRTC.instance.roomManager.joinRoom(
roomInfo,
micEnabled: true,
cameraEnabled: true,
screenShareEnabled: false,
);

Note: The SDK currently supports both screenShareEnabled and the legacy typo scrennShareEnabled. The docs use screenShareEnabled.

3. Listen to Connection Status

import 'package:tgortcflutter/entity/const.dart';

void handleConnectStatus(String roomName, ConnectStatus status, String reason) {
print('Room $roomName: $status - $reason');

switch (status) {
case ConnectStatus.connecting:
print('Connecting...');
break;
case ConnectStatus.connected:
print('Connected to room');
break;
case ConnectStatus.reconnecting:
print('Reconnecting...');
break;
case ConnectStatus.reconnected:
print('Reconnected to room');
break;
case ConnectStatus.disconnected:
print('Disconnected from room');
break;
}
}

TgoRTC.instance.roomManager.addConnectListener(handleConnectStatus);
TgoRTC.instance.roomManager.removeConnectListener(handleConnectStatus);

4. Get Participants

final local = TgoRTC.instance.participantManager.getLocalParticipant();
final remotes = TgoRTC.instance.participantManager.getRemoteParticipants();
final all = TgoRTC.instance.participantManager.getAllParticipants();

TgoRTC.instance.participantManager.addNewParticipantListener((participant) {
print('New participant joined: ${participant.uid}');
});

5. Media Control and Events

Media control is only available for local participants.

import 'package:tgortcflutter/entity/const.dart';
import 'package:tgortcflutter/entity/video_info.dart';

final participant = TgoRTC.instance.participantManager.getLocalParticipant();

await participant?.setMicrophoneEnabled(true);
await participant?.setCameraEnabled(true);
await participant?.setScreenShareEnabled(true);
participant?.switchCamera();

await participant?.setSpeakerphoneOn(true, forceSpeakerOutput: false);
await participant?.toggleSpeakerphone();

final micEnabled = participant?.getMicrophoneEnabled() ?? false;
final cameraEnabled = participant?.getCameraEnabled() ?? false;
final screenShareEnabled = participant?.getScreenShareEnabled() ?? false;
final speakerEnabled = participant?.getSpeakerEnabled() ?? false;
final cameraPosition = participant?.getCameraPosition();
final audioLevel = participant?.getAudioLevel() ?? 0;
final isSpeaking = participant?.getIsSpeaking() ?? false;
final createdAt = participant?.createdAt;
final currentVideoInfo = participant?.currentVideoInfo;

void onMicChange(bool enabled) {
print('Microphone: ${enabled ? "on" : "off"}');
}

void onCameraChange(bool enabled) {
print('Camera: ${enabled ? "on" : "off"}');
}

void onSpeakerChange(bool enabled) {
print('Speaker: ${enabled ? "on" : "off"}');
}

void onScreenShareChange(bool enabled) {
print('Screen share: ${enabled ? "on" : "off"}');
}

void onCameraPositionChange(TgoCameraPosition position) {
print('Camera position: $position');
}

void onSpeakingChange(bool speaking) {
print('Speaking: $speaking');
}

void onConnQualityChange(TgoConnectionQuality quality) {
print('Connection quality: $quality');
}

void onJoined() {
print('Participant joined');
}

void onLeave() {
print('Participant left');
}

void onTrackPublished() {
print('Track published');
}

void onTrackUnpublished() {
print('Track unpublished');
}

void onVideoInfoChange(VideoInfo info) {
print('Video: ${info.resolutionString}, ${info.bitrateString}');
}

participant?.addMicrophoneStatusListener(onMicChange);
participant?.addCameraStatusListener(onCameraChange);
participant?.addSpeakerStatusListener(onSpeakerChange);
participant?.addScreenShareStatusListener(onScreenShareChange);
participant?.addCameraPositionListener(onCameraPositionChange);
participant?.addSpeakingListener(onSpeakingChange);
participant?.addConnQualityListener(onConnQualityChange);
participant?.addJoinedListener(onJoined);
participant?.addLeaveListener(onLeave);
participant?.addTrackPublishedListener(onTrackPublished);
participant?.addTrackUnpublishedListener(onTrackUnpublished);
participant?.addVideoInfoListener(onVideoInfoChange);

participant?.removeMicrophoneStatusListener(onMicChange);
participant?.removeCameraStatusListener(onCameraChange);
participant?.removeSpeakerStatusListener(onSpeakerChange);
participant?.removeScreenShareStatusListener(onScreenShareChange);
participant?.removeCameraPositionListener(onCameraPositionChange);
participant?.removeSpeakingListener(onSpeakingChange);
participant?.removeConnQualityListener(onConnQualityChange);
participant?.removeJoinedListener(onJoined);
participant?.removeLeaveListener(onLeave);
participant?.removeTrackPublishedListener(onTrackPublished);
participant?.removeTrackUnpublishedListener(onTrackUnpublished);
participant?.removeVideoInfoListener(onVideoInfoChange);

6. Render Video Track

import 'package:flutter/material.dart';
import 'package:flutter_webrtc/flutter_webrtc.dart';
import 'package:livekit_client/livekit_client.dart';
import 'package:tgortcflutter/tgortc.dart';
import 'package:tgortcflutter/track/tgo_track_renderer.dart';

class VideoView extends StatefulWidget {
final TgoParticipant participant;

const VideoView({super.key, required this.participant});


State<VideoView> createState() => _VideoViewState();
}

class _VideoViewState extends State<VideoView> {
late final TgoTrackRenderer _renderer;


void initState() {
super.initState();
_renderer = TgoTrackRenderer(
source: TrackSource.camera,
fit: RTCVideoViewObjectFit.RTCVideoViewObjectFitCover,
mirror: true,
placeholder: const SizedBox.shrink(),
onTrackChange: (hasTrack) {
debugPrint('Track available: $hasTrack');
},
);
_renderer.setParticipant(widget.participant);
}


Widget build(BuildContext context) {
return _renderer.build();
}
}

7. Audio Management

final isSpeakerOn = TgoRTC.instance.audioManager.isSpeakerOn;
final canSwitchSpeaker = TgoRTC.instance.audioManager.canSwitchSpeakerphone;
final speakerOn = TgoRTC.instance.audioManager.speakerOn;

final inputDevices = await TgoRTC.instance.audioManager.getAudioInputDevices();
final outputDevices = await TgoRTC.instance.audioManager.getAudioOutputDevices();
final videoDevices = await TgoRTC.instance.audioManager.getDevices('videoinput');

await TgoRTC.instance.audioManager.setSpeakerphoneOn(true);
await TgoRTC.instance.audioManager.toggleSpeakerphone();

if (inputDevices.isNotEmpty) {
await TgoRTC.instance.audioManager.switchAudioInputDevice(
inputDevices.first.deviceId,
);
}

if (outputDevices.isNotEmpty) {
await TgoRTC.instance.audioManager.switchAudioOutputDevice(
outputDevices.first.deviceId,
);
}

void onDeviceChange(List<dynamic> devices) {
print('Devices changed: $devices');
}

TgoRTC.instance.audioManager.addDeviceChangeListener(onDeviceChange);
TgoRTC.instance.audioManager.removeDeviceChangeListener(onDeviceChange);

8. Leave Room

await TgoRTC.instance.roomManager.leaveRoom();

API Reference

TgoRTC

PropertyTypeDescription
instanceTgoRTCSingleton instance
optionsOptionsSDK configuration
roomManagerTgoRoomManagerRoom management
participantManagerTgoParticipantManagerParticipant management
audioManagerTgoAudioManagerAudio management

TgoRoomManager

MethodDescription
joinRoom(roomInfo, {micEnabled, cameraEnabled, screenShareEnabled})Join a room
leaveRoom()Leave current room
addConnectListener(listener)Add connection status listener
removeConnectListener(listener)Remove connection status listener
addVideoInfoListener(listener)Add local video info listener
removeVideoInfoListener(listener)Remove local video info listener
PropertyDescription
roomLiveKit Room instance
currentRoomInfoCurrent room info
currentVideoInfoCurrent local video info

TgoParticipantManager

MethodDescription
getLocalParticipant()Get local participant
getRemoteParticipants()Get remote participants
getAllParticipants()Get all participants
getPendingParticipantCreatedAt()Get creation times of pending participants
removeParticipantByUid(uid)Remove a pending participant by UID
removePendingParticipants(roomName, uids)Remove pending participants
missed(roomName, uids)Mark participants as missed
inviteParticipant(uids, {roomName})Invite participants
invite(roomName, uids)Invite participants
addNewParticipantListener(listener)Listen for new participants
removeNewParticipantListener(listener)Remove new participant listener

TgoParticipant

Media Control Methods

MethodDescription
setMicrophoneEnabled(enabled)Enable/disable microphone
setCameraEnabled(enabled)Enable/disable camera
setScreenShareEnabled(enabled)Enable/disable screen share
switchCamera()Switch front/back camera
setSpeakerphoneOn(on, {forceSpeakerOutput})Set speakerphone
toggleSpeakerphone()Toggle speakerphone

Status Methods

MethodDescription
getMicrophoneEnabled()Get microphone status
getCameraEnabled()Get camera status
getScreenShareEnabled()Get screen share status
getSpeakerEnabled()Get speaker status
getCameraPosition()Get camera position
getVideoTrack({source})Get video track
getAudioLevel()Get current audio level
getIsSpeaking()Whether the participant is speaking

Event Listener Methods

MethodDescription
addMicrophoneStatusListener(listener)Listen for microphone status changes
addCameraStatusListener(listener)Listen for camera status changes
addSpeakerStatusListener(listener)Listen for speaker status changes
addScreenShareStatusListener(listener)Listen for screen share status changes
addCameraPositionListener(listener)Listen for camera position changes
addSpeakingListener(listener)Listen for speaking status changes
addConnQualityListener(listener)Listen for connection quality changes
addJoinedListener(listener)Listen for participant join
addLeaveListener(listener)Listen for participant leave
addTrackPublishedListener(listener)Listen for track published events
addTrackUnpublishedListener(listener)Listen for track unpublished events
addVideoInfoListener(listener)Listen for video info changes
remove...Listener(listener)Remove the corresponding listener

Properties

PropertyDescription
uidParticipant ID
isLocalWhether this is the local participant
isJoinedWhether the participant has joined
createdAtCreation time
currentVideoInfoCurrent video info

TgoTrackRenderer

TgoTrackRenderer({
TrackSource source = TrackSource.camera,
RTCVideoViewObjectFit fit = RTCVideoViewObjectFit.RTCVideoViewObjectFitCover,
bool? mirror,
Widget? placeholder,
ValueChanged<bool>? onTrackChange,
})
MethodDescription
setParticipant(participant)Set participant
clear()Clear participant
build()Build the video widget

TgoAudioManager

Method / PropertyDescription
isSpeakerOnWhether speakerphone is currently enabled
canSwitchSpeakerphoneWhether speakerphone switching is supported
speakerOnUnderlying hardware speaker state
currentAudioInputDeviceIdCurrent input device ID
currentAudioOutputDeviceIdCurrent output device ID
addDeviceChangeListener(listener)Add device change listener
removeDeviceChangeListener(listener)Remove device change listener
setSpeakerphoneOn(on, {forceSpeakerOutput})Set speakerphone
toggleSpeakerphone()Toggle speakerphone
getAudioInputDevices()Get audio input devices
getAudioOutputDevices()Get audio output devices
getDevices(kind)Get devices by type
switchAudioInputDevice(deviceId, {setAsDefault = true})Switch audio input device
switchAudioOutputDevice(deviceId, {setAsDefault = true})Switch audio output device

Enums

ConnectStatus

enum ConnectStatus {
connecting,
connected,
reconnecting,
reconnected,
disconnected,
}

RTCType

enum RTCType {
audio,
video,
}

TgoConnectionQuality

enum TgoConnectionQuality {
unknown,
excellent,
good,
poor,
lost,
}

TgoCameraPosition

enum TgoCameraPosition {
front,
back,
}

RoomInfo Class

class RoomInfo {
String roomName;
String token;
String url;
String loginUID;
String creatorUID;
int maxParticipants;
RTCType rtcType;
bool isP2P;
List<String> uidList;
int timeout;

String getP2PToUID();
bool isCreator();
}

Configuration Options

class Options {
bool mirror = false;
bool debug = true;
}

Best Practices

Save Participant References

Avoid repeatedly calling getLocalParticipant(). Save the local participant reference after connection and remove listeners in dispose().

Enable Media After Connection

Based on the actual Flutter integration example, on Android it is safer to join the room first and enable local media after connection to avoid flutter_webrtc state-sync issues on some devices:

await TgoRTC.instance.roomManager.joinRoom(
roomInfo,
micEnabled: false,
cameraEnabled: false,
);

final local = TgoRTC.instance.participantManager.getLocalParticipant();
await local?.setMicrophoneEnabled(true);
await local?.setCameraEnabled(true);

Handle Pending Participants

If your business layer already knows which invited users did not answer, you can remove them manually:

TgoRTC.instance.participantManager.removePendingParticipants(
roomInfo.roomName,
['user_b', 'user_c'],
);

Platform Configuration

Android

Add permissions in android/app/src/main/AndroidManifest.xml:

<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />

iOS

Add permission descriptions in ios/Runner/Info.plist:

<key>NSCameraUsageDescription</key>
<string>Camera access is required for video calls</string>
<key>NSMicrophoneUsageDescription</key>
<string>Microphone access is required for voice calls</string>