Video Conference

Learn how to add video conference calls to your app.

🚧

This feature is available for customers on the Enterprise plan only. Take advantage of Enterprise features to unlock new value and opportunities for users. For more information and if you want to request a Demo, please contact us by mail: [email protected].

QuickBlox provides a Multiparty Video Conferencing solution allowing to set up a video conference between 10-12 people. It is built on top of WebRTC SFU technologies.

Features supported:

- Video/Audio Conference with 10-12 people.
- Join/Rejoin video room functionality (like Skype).
- Mute/Unmute audio/video stream.
- Switch video input device (camera).

Initialize

In order to start working with Multiparty Video Conferencing API, you need to initialize the conference module by calling the init() method. The conference module allows to process conference calls. If the module is not initialized, it will not be able to create the session and process calls consequently.

🚧

You must call the init() method before calling any other methods. If you attempt to call a method without initializing the module, the error is returned.

try {
  String conferenceServer = "your_conference_server";
  await QB.conference.init(conferenceServer);
} on PlatformException catch (e) {
  // Some error occurred, look at the exception message for more details
}
ArgumentRequiredDescription
conferenceServeryesA conference server endpoint.

Manage calls

To process events such as a received video track, you should subscribe to an event(s) first and assign an event handler. If you've subscribed to the event(s), you receive StreamSubscription that you should unsubscribe when you need, for example, in the dispose() method.

You can subscribe to several events at the same time. However, you should handle these events as different subscriptions. For example, if you subscribe to three events, you should call three subscribeConferenceEvent() methods. And if you need to unsubscribe from these three events, you should have the same number of unsubscriptions.

// Conference Events
// QBConferenceEventTypes.CONFERENCE_VIDEO_TRACK_RECEIVED
// QBConferenceEventTypes.CONFERENCE_PARTICIPANT_RECEIVED
// QBConferenceEventTypes.CONFERENCE_PARTICIPANT_LEFT
// QBConferenceEventTypes.CONFERENCE_ERROR_RECEIVED
// QBConferenceEventTypes.CONFERENCE_CLOSED
// QBConferenceEventTypes.CONFERENCE_STATE_CHANGED

StreamSubscription? _someSubscription;

// Unsubscribe

@override
void dispose() {
  if(_someSubscription != null) {
  	_someSubscription!.cancel();
    _someSubscription = null;
  }
}

// Subscribe
String event = QBConferenceEventTypes.CONFERENCE_CLOSED;

try {
  someSubscription = await QB.conference.subscribeConferenceEvent(event ,(data) {
  String sessionId = data["payload"]["sessionId"];
});
} on PlatformException catch (e) {
  // Some error occured, look at the exception message for more details  
}

The table below lists all supported conference session events.

EventDescription
QBConferenceEventTypes.
CONFERENCE_VIDEO_TRACK_RECEIVED
A remote video track has been received by the remote participant.
QBConferenceEventTypes.
CONFERENCE_PARTICIPANT_RECEIVED
A new participant has joined a conference session.
QBConferenceEventTypes.
CONFERENCE_PARTICIPANT_LEFT
A participant has left a conference session.
QBConferenceEventTypes.
CONFERENCE_ERROR_RECEIVED
An error was received.
QBConferenceEventTypes.
CONFERENCE_CLOSED
A conference session was closed.
QBConferenceEventTypes.
CONFERENCE_STATE_CHANGED
A conference session state has been changed.

Create session

To be able to interact with the Video Conferencing API, you need to create a conference session by calling the create() method. Each conference session is tied to a specific dialogId taken from the QuickBlox Chat. See this section for more information about dialogs.

🚧

It is important to store the current session in the session variable to be able to interact with the current conference session. For example, if you don't store the current session, you won't be able to hang up or reject a call.

// Session Types
// QBConferenceSessionTypes.VIDEO
// QBConferenceSessionTypes.AUDIO

...

QBConferenceRTCSession? _session;

...

String dialogId = "1148462029";
String sessionType = QBConferenceSessionTypes.VIDEO;

try {
  _session = await QB.conference.create(dialogId, sessionType);
  int sessionId = session!.id;
} on PlatformException catch (e) {
  // Some error occurred, look at the exception message for more details 
}
ArgumentRequiredDescription
sessionTypeyesConference session type: QBConferenceSessionTypes.VIDEO, QBConferenceSessionTypes.AUDIO.
dialogIdyesID of the dialog. Taken from the QuickBlox Chat.

Join video room

Once a conference session is created, you need to establish a call. To establish a call, you need to join an already-created conference session by calling the joinAsPublisher() method. This method joins the session and publishes your feed making you an active publisher in the room. Everyone in the room will be able to subscribe and receive your feed. Once the room is joined, you receive an array of participants' IDs.

🚧

Make sure to subscribe to each participant to be able to receive video/audio tracks from them. If you don't subscribe, you won't receive audio and video of the participant joined to the room. See this section for more information.

String sessionId = "114846dfsJKJDdls8dsfj2029";

try {
  List<int?> participants = await QB.conference.joinAsPublisher(sessionId);
  for (int i = 0; i < participants.length; i++) {
    int userId = participants[i]!;
    subscribeToParticipant(sessionId, userId);
  }
} on PlatformException catch (e) {
  // Some error occurred, look at the exception message for more details  
}
ArgumentRequiredDescription
sessionIdyesConference session ID. Received from the QBConferenceRTCSession object that is returned in the response to the create() method.

Subscribe

Use the subscribeToParticipant() method to subscribe to a participant.

String sessionId = "114846dfsJKJDdls8dsfj2029";
int userid = 567527986;

try {
  await QB.conference.subscribeToParticipant(sessionId, userId);
} on PlatformException catch (e) {
  // Some error occurred, look at the exception message for more details
}
ArgumentRequiredDescription
sessionIdyesConference session ID.
userIdyesUser ID. Taken from the array of participants' IDs received in the responce to the joinAsPublisher() method.

Unsubscribe

Use the unsubscribeFromParticipant() method to unsubscribe from the participant's audio/video track.

String sessionId = "114846dfsJKJDdls8dsfj2029";
int userid = 567527986;

try {
  await QB.conference.unsubscribeFromParticipant(sessionId, userId);
} on PlatformException catch (e) {
  // Some error occurred, look at the exception message for more details
}
ArgumentRequiredDescription
sessionIdyesConference session ID.
userIdyesUser ID. Taken from the array of participants' IDs received in the responce to the joinAsPublisher() mthod.

Set up video view

Set up the ConferenceVideoView for remote and local video tracks to be able to show the video. The ConferenceVideoView allows displaying the video stream while the ConferenceVideoViewController allows to control the video view. Thus, you can play, release the video stream from video view.

  • A remote video track represents a remote peer video stream from a remote camera app. Specify the initial value to ConferenceVideoView - RTCVideoViewController for the remote camera app of the remote peer. There can be multiple remote video tracks in the conference call. In this case, you should set up the ConferenceVideoView for each remote video track individually.
  • A local video track represents a local peer video stream from a local camera app. Specify the initial value to ConferenceVideoView - RTCVideoViewController for the local camera app of the remote peer. There can be only one local video track in the conference call.
...
ConferenceVideoViewController? _localVideoViewController
ConferenceVideoViewController? _remoteVideoViewController

// Some widgets code 
...

child: new Container(
  margin: EdgeInsets.fromLTRB(10.0, 10.0, 10.0, 10.0),
  width: 160.0,
  height: 160.0,
  child: ConferenceVideoView(
    onVideoViewCreated: onRemoteVideoViewCreated,
),
  decoration: BoxDecoration(color: Colors.black54),
)

child: Container(
  margin: EdgeInsets.fromLTRB(10.0, 10.0, 10.0, 10.0),
  width: 160.0,
  height: 160.0,
  child: ConferenceVideoView(
    onVideoViewCreated: onLocalVideoViewCreated,
  ),
  decoration: BoxDecoration(color: Colors.black54),
)

...

void onRemoteVideoViewCreated(ConferenceVideoViewController controller) {
  _remoteVideoViewController = controller;
}

void onLocalVideoViewCreated(ConferenceVideoViewController controller) {
  _localVideoViewController = controller;
}

...

Subscribe to the QBConferenceEventTypes.CONFERENCE_VIDEO_TRACK_RECEIVED event. Thus, once the SDK receives data that a remote video track was received, it creates the event of CONFERENCE_VIDEO_TRACK_RECEIVED type with userId and sessionId properties. See this section to learn how to subscribe the event.

After this, invoke method play() and pass sessionId and userId parameters to it. If the userId matches with the one in properties, the video starts playing.

...

String sessionId = "114846dfsJKJDdls8dsfj2029";
int opponentId = 2182763;

Future<void> startRenderingRemote() async {
  try {
    await remoteVideoViewController.play(sessionId, opponentId);
  } on PlatformException catch (e) {
    // Some error occurred, look at the exception message for more details
  }
}

String sessionId = "114846dfsJKJDdls8dsfj2029";
int opponentId = 2182763;

Future<void> startRenderingLocal() async {
  try {
    await localVideoViewController.play(sessionId, userId);
  } on PlatformException catch (e) {
    // Some error occurred, look at the exception message for more details
  }
}
ArgumentRequiredDescription
sessionIdyesConference session ID.
userIdyesThe ID of the local peer.
opponentIdyesThe ID of the remote peer.

Mute local audio

You can mute/unmute your own audio by using the enableAudio() method.

String sessionId = "114846dfsJKJDdls8dsfj2029";
bool enable = true;

try {
  await QB.conference.enableAudio(sessionId, enable: enable);
} on PlatformException catch (e) {
  // Some error occurred, look at the exception message for more details
}
ArgumentRequiredDescription
sesssionIdyesConference session ID.
enablednoBoolean parameter. Allows to enable/disable a local audio.

Disable local video

You can enable/disable your own video by using the enableVideo() method.

String sessionId = "114846dfsJKJDdls8dsfj2029";
bool enable = true;

try {
  await QB.conference.enableVideo(sessionId, enable: enable);
} on PlatformException catch (e) {
  // Some error occurred, look at the exception message for more details
}
ArgumentRequiredDescription
sessionIdyesConference session ID.
enablednoBoolean parameter. Allows to enable/disable a local video.

Switch video input device

You can switch a video input to the rear or front camera. The SDK automatically finds all cameras and chooses the two cameras with the highest video quality. Call the switchCamera() method to switch between the two cameras.

String sessionId = "114846dfsJKJDdls8dsfj2029";

try {
  await QB.conference.switchCamera(sessionId);
} on PlatformException catch (e) {
  // Some error occurred, look at the exception message for more details
}
ArgumentRequiredDescription
sessionIdyesConference session ID.

Switch audio output device

You can switch an audio output. Call the switchAudioOutput() method and pass the type of the audio device to it.

🚧

You can switch the audio input only after calling the create() method.

// Audio output
// EARSPEAKER = 0
// LOUDSPEAKER = 1
// HEADPHONES = 2
// BLUETOOTH = 3

int output = QBConferenceAudioOutputTypes.LOUDSPEAKER;

try {
  await QB.conference.switchAudioOutput(output);
} on PlatformException catch (e) {
  // Some error occurred, look at the exception message for more details
}
ArgumentRequiredDescription
outputyesType of the audio device:
QBConferenceAudioOutputTypes.EARSPEAKER ,
QBConferenceAudioOutputTypes.LOUDSPEAKER ,
QBConferenceAudioOutputTypes.HEADPHONES,
QBConferenceAudioOutputTypes.BLUETOOTH.

Leave video room

To leave the video room, use the leave() method. After calling this method, the current session is deleted from SDK and you can't access this session any more.

String sessionId = "114846dfsJKJDdls8dsfj2029";

try {
  await QB.conference.leave(sessionId);
} on PlatformException catch (e) {
  // Some error occurred, look at the exception message for more details
}
ArgumentRequiredDescription
sessionIdyesConference session ID.

Release resource

If you don't want to receive and process video calls, for example, when a user is logged out or the ConferenceVideoView is going to close, you have to release the conference module. Call the release() method that allows to unregister the conference module from receiving any video conference events and closes existing signaling channels.

If you want to create another conference session after the release() method, you should call the init() method first to initialize the conference module. After the module is initialized, you can create another conference session by calling the create() method.

...

ConferenceVideoViewController? _localVideoViewController;
ConferenceVideoViewController? _remoteVideoViewController;

...

try {
  await QB.conference.release();

  // Release video views
  await _localVideoViewController!.release();
  await _remoteVideoViewController!.release();
} on PlatformException catch (e) {
  // Some error occurred, look at the exception message for more details
}

📘

The release() method should be called when a video track is no more valid. If you don't call this method, you will get a memory leak.


What’s Next