Group video call
This page provides a code example for implementing a group video call.
Prerequisites
Before you begin, you must do the following:
- Initialize PlanetKit.
- Get a proper access token.
- Check the overall API usage flow in Group call flow.
Considerations for implementing a group video call
After calling joinConference()
, you must check the reason
property of the returned PlanetKitConferenceJoinResult
.
- If the
reason
isPlanetKitStartFailReason.none
, it means success. - Otherwise, it means failure and you must take an appropriate action based on the
reason
.
Implement event delegates
Implement the event delegates to be used on the call.
PlanetKitConferenceDelegate
is used to handle status change events of a group call.PlanetKitMyMediaStatusDelegate
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.
extension ConferenceDelegateExample : PlanetKitConferenceDelegate {
func didConnect(_ conference: PlanetKitConference, connected: PlanetKitConferenceConnectedParam) {
// This is called when the call is connected.
// Write your own code here.
}
func didDisconnect(_ conference: PlanetKitConference, disconnected: PlanetKitDisconnectedParam) {
// This is called when the call is disconnected.
// Write your own code here.
}
func peerListDidUpdate(_ conference: PlanetKitConference, updated: PlanetKitConferencePeerListUpdateParam) {
// This is called when the list of peers is updated.
// Write your own code here.
}
func peersVideoDidUpdate(_ conference: PlanetKitConference, updated: PlanetKitConferenceVideoUpdateParam) {
// This is called when the video of one or more peers is updated.
// Write your own code here.
}
//
// Also, you should implement other methods defined in the PlanetKitConferenceDelegate protocol.
//
...
}
extension MyMediaStatusDelegateExample: PlanetKitMyMediaStatusDelegate {
func didMuteMic(_ myMediaStatus: PlanetKitMyMediaStatus) {
// This is called when the local user's audio is muted.
// Write your own code here.
}
func didUnmuteMic(_ myMediaStatus: PlanetKitMyMediaStatus) {
// This is called when the local user's audio is unmuted.
// Write your own code here.
}
func didUpdateAudioDescription(_ myMediaStatus: PlanetKitMyMediaStatus, description: PlanetKitMyAudioDescription) {
// This is called when the local user's audio description is updated.
// Write your own code here.
}
func didUpdateVideoStatus(_ myMediaStatus: PlanetKitMyMediaStatus, status: PlanetKitVideoStatus) {
// This is called when the local user's video status is updated.
// Write your own code here.
}
//
// Also, you should implement other methods defined in the PlanetKitMyMediaStatusDelegate protocol.
//
...
}
Preview the local user's video
The preview feature allows the local user to preview their own video regardless of the group call session.
To starting previewing the local user's video, call startPreview()
of PlanetKitCameraManager
.
func startPreviewExample(delegate: PlanetKitVideoOutputDelegate)
{
PlanetKitCameraManager.shared.startPreview(delegate)
}
To stop previewing the local user's video, call stopPreview()
of PlanetKitCameraManager
.
func stopPreviewExample(delegate: PlanetKitVideoOutputDelegate)
{
PlanetKitCameraManager.shared.stopPreview(delegate)
}
Join a group call
The steps for joining a group call are as follows:
- Build a setting through
PlanetKitJoinConferenceSettingBuilder
. - Create
PlanetKitConferenceParam
withPlanetKitConferenceDelegate
, and set themediaType
property to.audiovideo
. - Call
PlanetKitManager.shared.joinConference()
. - Check the
PlanetKitConferenceJoinResult
.
The local user's initial video state can be set with the initialMyVideoState
property of PlanetKitConferenceParam
.
- The default value of the
initialMyVideoState
property isPlanetKitInitialMyVideoState.resume
. - If the local user's initial video state is set to paused by setting
initialMyVideoState
toPlanetKitInitialMyVideoState.pause
, the local user's video is not transmitted. The local user's video can be transmitted by callingresumeMyVideo()
after the call is connected.
class ParticipantExample
{
var conference: PlanetKitConference?
var myMediaStatusDelegate: MyMediaStatusDelegateExample
}
...
extension ParticipantExample
{
func joinConferenceExample(myId: String, myServiceId: String, roomId: String, roomServiceId: String, accessToken: String, delegate: PlanetKitConferenceDelegate, initialMyVideoState: PlanetKitInitialMyVideoState) {
let myUserId = PlanetKitUserId(id: myId, serviceId: myServiceId)
let settings = try! PlanetKitJoinConferenceSettingBuilder().build()
let param = PlanetKitConferenceParam(myUserId: myUserId, roomId: roomId, roomServiceId: roomServiceId, displayName: nil, delegate: delegate, accessToken: accessToken)
param.mediaType = .audiovideo
param.initialMyVideoState = initialMyVideoState
let result = PlanetKitManager.shared.joinConference(param: param, settings: settings)
guard result.reason == .none else {
NSLog("Failed reason: result. \(result.reason)")
return
}
// The result.conference instance is a conference instance for calling other APIs from now on.
// You must keep this instance in your own context.
// In this example, the "conference" variable holds the instance.
conference = result.conference
}
}
Set the media status event delegate for the local user
Once the call is connected, add the media status event delegate for the local user.
extension ParticipantExample
{
func addMyMediaStatusHandlerExample() {
conference.myMediaStatus.addHandler(myMediaStatusDelegate) {
// completion callback
}
}
}
Add a video view for the local user
To add a video view for the local user, create a PlanetKitMTKView
(myVideoView
), add it as a subview to the local view, and set it as the receiver of the local user's video stream using addReceiver()
of PlanetKitVideoStream
.
The rendering of the video starts or stops according to the local user's video status.
#if os(macOS)
typealias UIView = NSView
#endif
extension YourConferenceViewController {
@IBOutlet weak var localView: UIView!
var conference: PlanetKitConference!
...
func addMyVideoViewExample()
{
let myVideoView = PlanetKitMTKView(frame: localView.bounds, device: nil)
localView.addSubview(myVideoView)
conference.myVideoStream.addReceiver(myVideoView)
}
}
Add a video view for a peer
To add a video view for a peer, create a PlanetKitMTKView
(peerVideoView
) and add it as a subview to the peer view.
#if os(macOS)
typealias UIView = NSView
#endif
class YourPeerView: UIView {
@IBOutlet weak var peerView: UIView!
var peerVideoView: PlanetKitMTKView!
...
override public func awakeFromNib() {
super.awakeFromNib()
peerVideoView = PlanetKitMTKView(frame: peerView.bounds, device: nil)
peerVideoView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
peerView.addSubview(peerVideoView)
}
}
Create peer control for each peer
When the peer list is updated, create PlanetKitPeerControl
for newly added peers and register a PlanetKitPeerControlDelegate
object. You can handle the status change of each peer using the PlanetKitPeerControlDelegate
.
#if os(macOS)
typealias UIView = NSView
#endif
class YourPeerView: UIView {
...
var peerControl: PlanetKitPeerControl?
var peerVideoView: PlanetKitMTKView!
...
func setupPeerControl(for peer: PlanetKitConferencePeer, in conference: PlanetKitConference) {
guard let peerControl = conference.createPeerControl(peer: peer) else {
return
}
peerControl.register(self) { success in
// Write your own code here.
}
self.peerControl = peerControl
}
func setVideoEnabled(_ enable: Bool) {
if enable {
peerControl.startVideo(maxResolution: .recommended, delegate: peerVideoView) { success in
// Write your own code here.
}
}
else {
peerControl.stopVideo() { success in
// Write your own code here.
}
}
}
}
extension YourPeerView: PlanetKitPeerControlDelegate {
func didMuteMic(_ peerControl: PlanetKitPeerControl) {
// This is called when the local user's audio is muted.
// Write your own code here.
}
func didUnmuteMic(_ peerControl: PlanetKitPeerControl) {
// This is called when the local user's audio is unmuted.
// Write your own code here.
}
func didUpdateVideo(_ peerControl: PlanetKitPeerControl, subgroup: PlanetKitSubgroup, status: PlanetKitVideoStatus) {
DispatchQueue.main.async {
self.setVideoEnabled(status.isEnabled)
// This is called when the local user's video status is changed.
// Write your own code here.
}
}
//
// Also, you should implement other methods defined in the PlanetKitPeerControlDelegate protocol.
//
...
}
Leave a group call
To leave a group call, call leaveConference()
.
extension ParticipantExample
{
func leaveConferenceExample() {
conference.leaveConference()
}
}
Implement Apple CallKit in the application
This step applies to iOS applications only.
CallKit is one of Apple's frameworks that provides the calling interface. PlanetKit SDK supports three options for CallKit: integration of user CallKit implementation, integration of PlanetKit internal implementation, and no integration.
By default, PlanetKit SDK joins a group call without CallKit integration. If you want to integrate your own implementation of CallKit, you must set type
of PlanetKitCallKitSetting
to user
when joining a group call with PlanetKit SDK.
To implement CallKit in your application, do the following:
-
Create a
PlanetKitCallKitSetting
instance and settype
ofPlanetKitCallKitSetting
touser
. -
Pass the instance to
withCallKitSettingsKey()
ofPlanetKitJoinConferenceSettingBuilder
and build settings.// Code for Step 1 and Step 2
func createJoinConferenceSettingsWithUserCallKitExample() -> [String: Any] {
let callKitSetting = PlanetKitCallKitSetting(type: .user, param: nil)
var settingsBuilder = try! PlanetKitJoinConferenceSettingBuilder().withCallKitSettingsKey(setting: callKitSetting)
let joinConferenceSettings = settingsBuilder.build()
} -
On
provider(_:didActivate:)
ofCXProviderDelegate
, callnotifyCallKitAudioActivation()
ofPlanetKitConference
.// Code for Step 3
extension YourCallKitHandler : CXProviderDelegate {
...
func provider(_ provider: CXProvider, didActivate audioSession: AVAudioSession) {
// PlanetKitConference instance created from PlanetKitManager.joinConference()
conference.notifyCallKitAudioActivation()
}
...
}
For more information, see CallKit documentation.