VideoCall SDK
Make an video call easily
Supported platforms
VideoCall SDK for Flutter is designed to work across all platforms supported by Flutter:
- Android
- iOS
- Web
- macOS
- Windows
- Linux
Example app
We built a multi-user conferencing app as an example in the example/ folder. LiveKit is compatible cross-platform: you could join the same room using any of our supported realtime SDKs.
iOS
Camera and microphone usage need to be declared in your Info.plist
file.
<dict>
...
<key>NSCameraUsageDescription</key>
<string>$(PRODUCT_NAME) uses your camera</string>
<key>NSMicrophoneUsageDescription</key>
<string>$(PRODUCT_NAME) uses your microphone</string>
Your application can still run the voice call when it is switched to the background if the background mode is enabled. Select the app target in Xcode, click the Capabilities tab, enable Background Modes, and check Audio, AirPlay, and Picture in Picture.
Your Info.plist
should have the following entries.
<dict>
...
<key>UIBackgroundModes</key>
<array>
<string>audio</string>
</array>
Notes
Since xcode 14 no longer supports 32bit builds, and our latest version is based on libwebrtc m104+ the iOS framework no longer supports 32bit builds, we strongly recommend upgrading to flutter 3.3.0+. if you are using flutter 3.0.0 or below, there is a high chance that your flutter app cannot be compiled correctly due to the missing i386 and arm 32bit framework #132 #172.
You can try to modify your {projects_dir}/ios/Podfile
to fix this issue.
post_install do |installer|
installer.pods_project.targets.each do |target|
flutter_additional_ios_build_settings(target)
target.build_configurations.each do |config|
# Workaround for https://github.com/flutter/flutter/issues/64502
config.build_settings['ONLY_ACTIVE_ARCH'] = 'YES' # <= this line
end
end
end
For iOS, the minimum supported deployment target is 13.0
. You will need to add the following to your Podfile.
platform :ios, '13.0'
You may need to delete Podfile.lock
and re-run pod install
after updating deployment target.
Android
We require a set of permissions that need to be declared in your AppManifest.xml
. These are required by Flutter WebRTC, which we depend on.
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.your.package">
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_INTERNAL_STORAGE" />
...
</manifest>
To your Android Manifest, under the <application>
tag, add the following:
<service
android:name="com.foregroundservice.ForegroundService"
android:foregroundServiceType="mediaProjection">
</service>
Import SDK:
import 'package:video_call_sdk/video_call_sdk.dart';
To authenticate SDK with system for enable using SDK:
final authSuccess = await MTVideoCallPlugin.instance.authenticate(apiKey: 'your_api_key');
Get hardware info device is using:
List<MediaDevice> audioInputs = MTVideoCallPlugin.instance.getDeviceAudioInput();
List<MediaDevice> videoInputs = MTVideoCallPlugin.instance.getDeviceVideoInput();
Get queue support:
List<MTQueue> queues = await MTVideoCallPlugin.instance.getQueues();
Start video call:
Using video call UI template of SDK
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => MTCallingPage(
user: MTUser(
name: "name_of_end_user", // Required
email: "email_of_end_user",
phone: "phone_of_end_user",
),
queue: queueSelected,
device: videoInputSelected,
),
),
);
Using method was provided from SDK
First of all, add listener from MTRoomEventListener or TrackMTTrackListener
class YourPageState extends StatefulWidget {
const YourPageState({super.key});
@override
State<YourPageState> createState() => _YourPageStateState();
}
class _YourPageStateState extends State<YourPageState> with MTRoomEventListener, MTTrackListener{
@override
void initState() {
// TODO: implement initState
super.initState();
MTVideoCallPlugin.instance.addMTRoomEventListener(this);
MTVideoCallPlugin.instance.addMTTrackEventListener(this);
}
@override
Widget build(BuildContext context) {
return const Placeholder(); //Writing for your UI
}
@override
void onConnectedRoom(Room room, String? metaData) {
// TODO: implement onConnectedRoom
super.onConnectedRoom(room, metaData);
}
@override
void onDisconnectedRoom(DisconnectReason? reason) async {
// TODO: implement onDisconnectedRoom
super.onDisconnectedRoom(reason);
// Remove listener
// You can also remove listener in dispose callback
MTVideoCallPlugin.instance.removeMTRoomEventListener(this);
MTVideoCallPlugin.instance.removeMTTrackEventListener(this);
}
@override
void onParticipantConnectedRoom(RemoteParticipant participant) async {
// TODO: implement onParticipantConnectedRoom
super.onParticipantConnectedRoom(participant);
}
@override
void onParticipantDisconnectedRoom(RemoteParticipant participant) async {
// TODO: implement onParticipantDisconnectedRoom
super.onParticipantDisconnectedRoom(participant);
}
@override
void onRemoteUnMutedTrack(
TrackPublication<Track> publication, Participant<TrackPublication<Track>> participant) {
// TODO: implement onRemoteUnMutedTrack
super.onRemoteUnMutedTrack(publication, participant);
print("onRemoteUnMutedTrack: Called");
}
@override
void onRemoteMutedTrack(TrackPublication<Track> publication, Participant participant) {
// TODO: implement onRemoteMutedTrack
super.onRemoteMutedTrack(publication, participant);
print("onRemoteMutedTrack: Called");
}
@override
void onLocalTrackPublished(
LocalParticipant localParticipant, LocalTrackPublication<LocalTrack> publication) {
// TODO: implement onLocalTrackPublished
super.onLocalTrackPublished(localParticipant, publication);
}
@override
void onLocalTrackUnPublished(
LocalParticipant localParticipant, LocalTrackPublication<LocalTrack> publication) {
// TODO: implement onLocalTrackUnPublished
super.onLocalTrackUnPublished(localParticipant, publication);
}
@override
void onReceiveData(List<int> data, RemoteParticipant? participant, String? topic) {
// TODO: implement onReceiveData
super.onReceiveData(data, participant, topic);
}
@override
void onTrackSubscribed(
RemoteTrackPublication<RemoteTrack> publication, RemoteParticipant participant, Track track) {
// TODO: implement onTrackSubscribed
super.onTrackSubscribed(publication, participant, track);
}
@override
void onTrackUnSubscribed(
RemoteTrackPublication<RemoteTrack> publication, RemoteParticipant participant, Track track) {
// TODO: implement onTrackUnSubscribed
super.onTrackUnSubscribed(publication, participant, track);
}
}
Initialize and connect to room. Using function following:
final user = MTUser(
name: "sample_name",
email: "sample_email",
phone: "sample_phone",
);
final queue = queues.first; // example
final room = await MTVideoCallPlugin.instance.startVideoCall(
user: user, // MTUser object
queue: queue,
);
await MTVideoCallPlugin.instance.setInputVideo(inputVideo);
final isCnSuccess = await MTVideoCallPlugin.instance.connect2Room(queue: widget.queue, user: widget.user, room: room);
Dis/Enable recording:
MTVideoCallPlugin.instance.enableRecording(true) // or false
Switch, turn on/off camera and microphone when making video call:
MTVideoCallPlugin.instance.changeVideoTrack(mediaDevice)
MTVideoCallPlugin.instance.enableVideo(true) // or false
MTVideoCallPlugin.instance.enableMicrophone(true) // or false
Finally, disconnect video call:
bool isSuccess = await MTVideoCallPlugin.instance.disconnectVideoCall();
Libraries
- listen/prototype/room_prototype
- listen/prototype/track_prototype
- listen/publisher/room_publisher
- listen/publisher/track_publisher
- models/option_video_call
- models/queue
- models/room
- models/user
- utils/constants
- utils/log
- utils/observing
- video_call_sdk
- view/page/calling_page
- view/widget/grid_track
- view/widget/local_video
- view/widget/video_track_part
- view/widget/video_widget