Skip to main content
Version: 1.0

Group video call

This page provides a code example for implementing a group video call.

Prerequisites

Before you begin, you must do the following:

Considerations for implementing a group video call

After calling joinConference(), you must check the reason property of the returned PlanetKitJoinConferenceResult.

  • If the reason is PlanetKitStartFailReason.none, it means success.
  • Otherwise, it means failure and you must take an appropriate action based on the reason.

Request device permissions

Use Dart permission_handler package to request microphone, phone, Bluetooth connection, and camera permission.

import 'package:permission_handler/permission_handler.dart';
final status = await [Permission.microphone, Permission.phone, Permission.bluetoothConnect, Permission.camera].request();

Prepare variables

Prepare variables for key properties and event handlers.

  • PlanetKitConferenceEventHandler is used to handle status change events of a group call. For more information, see Group call flow.
  • PlanetKitMyMediaStatusHandler is used to handle the local user's media status change events. You can update the local user's UI based on these events, such as when the mic becomes muted or unmuted, when the audio description is updated, or when the video status is updated.
final String _myUserId = "test user id";
final String _serviceId = "test service id";
PlanetKitConference? _conference;
List<Peer> _peers = [];

bool isMyAudioMuted = false;
bool isMyVideoPaused = false;
bool isVideoEnabled = false;

int volume = 0;

final _eventHandler = PlanetKitConferenceEventHandler(
onConnected: (conference) => print("connected"),
onDisconnected: (conference, reason, source, byRemote) => print("disconnected $reason"),
onPeerListUpdated: _onPeerListUpdated);

final _myMediaStatusHandler = PlanetKitMyMediaStatusHandler(
onAudioDescriptionUpdate: (status, averageVolumeLevel) => volume = averageVolumeLevel,
onMicMute: (status) => isMyAudioMuted = true,
onMicUnmute: (status) => isMyAudioMuted = false,
onVideoStatusUpdate: (status, videoStatus) {
if (videoStatus.state == PlanetKitVideoState.enabled) {
isMyVideoPaused = false;
isVideoEnabled = true;
} else if (videoStatus.state == PlanetKitVideoState.disabled) {
isVideoEnabled = false;
} else if (videoStatus.state == PlanetKitVideoState.paused) {
isMyVideoPaused = true;
isVideoEnabled = true;
}
});

Join a group call

To join a group call, call PlanetKitManager.instance.joinConference() with a PlanetKitJoinConferenceParam that you can create using PlanetKitJoinConferenceParamBuilder().

  • To join a group video call, call setMediaType() of PlanetKitJoinConferenceParamBuilder with PlanetKitMediaType.audiovideo.
  • The local user's initial video state can be set with setInitialMyVideoState() of PlanetKitJoinConferenceParamBuilder.
    • The default value of the initialMyVideoState property is PlanetKitInitialMyVideoState.resume.
    • If the local user's initial video state is set to paused by calling setInitialMyVideoState() with PlanetKitInitialMyVideoState.pause, the local user's video is not transmitted. To transmit the local user's video after the call is connected, call resumeMyVideo().
Future<bool> joinConference(String roomId, String accessToken) async {
var builder = PlanetKitJoinConferenceParamBuilder()
.setMyUserId(_myUserId)
.setMyServiceId(_serviceId)
.setRoomServiceId(_serviceId)
.setRoomId(roomId)
.setAccessToken(accessToken);
.setMediaType(PlanetKitMediaType.audiovideo)
.setInitialMyVideoState(initialMyVideoState);

PlanetKitJoinConferenceParam? param;
try {
param = builder.build();
} catch (error) {
print("failed to build join conference param $error");
return false;
}
final result =
await PlanetKitManager.instance.joinConference(param, _eventHandler);

if (result.reason != PlanetKitStartFailReason.none) {
print("join conference result ${result.reason}");
return false;
}

// Store conference instance and set MyMediaStatusHandler.
_conference = result.conference;
_conference?.myMediaStatus.setHandler(_myMediaStatusHandler);
return true;
}

Manage peers using PlanetKitPeerControl

Manage peers in the group call using PlanetKitConferenceEventHandler.onPeerListUpdated() and PlanetKitPeerControl. When the peer list is updated, create a PlanetKitPeerControl for the peer to be monitored.

class Peer {
final PlanetKitPeerControl control;
bool videoAvailable = false;

Peer({required this.control});

void register() async {
final handler =
PlanetKitPeerControlHandler(onVideoUpdate: (control, videoStatus) {
videoAvailable =
videoStatus.state == PlanetKitVideoState.enabled ? true : false;
});
await control.register(handler);
}

void unregister() async {
await control.unregister();
}

void startVideo(String viewId) async {
await control.startVideo(viewId);
}

void stopVideo(String viewId) async {
await control.stopVideo(viewId);
}
}

Render video

To render the peer's video, you must use PlanetKitVideoViewBuilder to create PlanetKitVideoView and add it toPlanetKitPeerControl.

After creating the PlanetKitVideoView for the peer's video, add the peer's video view to PlanetKitPeerControl by calling startVideo(viewId).

Your media type must be PlanetKitMediaType.audiovideo to view peer's video.

class PeerView extends StatelessWidget {
final Peer peer;
PeerView({required this.peer});


Widget build(BuildContext context) {
if (peer.videoAvailable) {
return VideoView(peer: peer);
} else {
return Text("video not available");
}
}
}

class VideoView extends StatelessWidget {
const VideoView({super.key, required this.peer});
final Peer peer;


Widget build(BuildContext context) {
final videoView = PlanetKitVideoViewBuilder.instance
.create(PlanetKitViewScaleType.fitCenter);

videoView.onCreate.listen((id) {
peer.startVideo(id);
});

videoView.onDispose.listen((id) {
peer.stopVideo(id);
});

return videoView;
}
}

Leave a group call

To leave a group call, call leaveConference().

Future<bool> leaveConference() async {
return await _conference?.leaveConference() ?? false;
}

Additional implementation for CallKit integration (Optional)

Note

This step applies to iOS applications only.

When using the CallKit framework, you must set callKitType to PlanetKitCallKitType.user in PlanetKitJoinConferenceParam.

Then, you must call PlanetKitConference.notifyCallKitAudioActivation() on CXProviderDelegate.provider(_ provider: CXProvider, didActivate audioSession: AVAudioSession) to ensure audio activation in PlanetKit.