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 (own and opponents).
- Display bitrate.
- Switch video input device (camera).

Conference endpoint

QBRTCConfig class introduces new setting for Conference - conference endpoint. To set a specific conference endpoint use the following method:

QBRTCConfig.setConferenceEndpoint("MyConferenceEndpoint")
[QBRTCConfig setConferenceEndpoint:@"MyConferenceEndpoint"];

📘

The endpoint should be a correct QuickBlox Conference server endpoint.

Use this method to get a current conference endpoint. The default value is nil.

let conferenceEndpoint = QBRTCConfig.conferenceEndpoint()
NSString *conferenceEndpoint = QBRTCConfig.conferenceEndpoint;

Conference client

The conference module has its own client.

Conference client delegate

Conference client delegate is inherited from base client delegate and has all of its protocol methods implemented as well.

Base client delegate protocol methods

All protocol methods below have their own explanation inlined and are optional.

/**
 *  Called by timeout with updated stats report for user ID.
 *
 *  @param session QBRTCSession instance
 *  @param report  QBRTCStatsReport instance
 *  @param userID  user ID
 *
 *  @remark Configure time interval with
 QBRTCConfig.setStatsReportTimeInterval(1.0).
 */
func session(_ session: QBRTCBaseSession, updatedStatsReport report: QBRTCStatsReport, forUserID userID: NSNumber) {   
}
 
/**
 *  Called when session state has been changed.
 *
 *  @param session QBRTCSession instance
 *  @param state session state
 *
 *  @discussion Use this to track a session state.
 As SDK 2.3 introduced states for session,
 you can now manage your own states based on this.
 */
func session(_ session: QBRTCBaseSession, didChange state: QBRTCConnectionState, forUser userID: NSNumber) {
}
 
/**
 *  Called when received remote audio track from user.
 *
 *  @param audioTrack QBRTCAudioTrack instance
 *  @param userID     ID of user
 */
func session(_ session: QBRTCBaseSession, receivedRemoteAudioTrack audioTrack: QBRTCAudioTrack, fromUser userID: NSNumber) {
}
 
/**
 *  Called when received remote video track from user.
 *
 *  @param videoTrack QBRTCVideoTrack instance
 *  @param userID     ID of user
 */
func session(_ session: QBRTCBaseSession, receivedRemoteVideoTrack videoTrack: QBRTCVideoTrack, fromUser userID: NSNumber) {
}
 
/**
 *  Called when connection is closed for user.
 *
 *  @param session QBRTCSession instance
 *  @param userID  ID of user
 */
func session(_ session: QBRTCBaseSession, connectionClosedForUser userID: NSNumber) {
}
 
/**
 *  Called when connection is initiated with user.
 *
 *  @param session QBRTCSession instance
 *  @param userID  ID of user
 */
func session(_ session: QBRTCBaseSession, startedConnectingToUser userID: NSNumber) {
}
 
/**
 *  Called when connection is established with user.
 *
 *  @param session QBRTCSession instance
 *  @param userID  ID of user
 */
func session(_ session: QBRTCBaseSession, connectedToUser userID: NSNumber) {
}
 
/**
 *  Called when disconnected from user.
 *
 *  @param session QBRTCSession instance
 *  @param userID  ID of user
 */
func session(_ session: QBRTCBaseSession, disconnectedFromUser userID: NSNumber) {
}
 
/**
 *  Called when connection failed with user.
 *
 *  @param session QBRTCSession instance
 *  @param userID  ID of user
 */
func session(_ session: QBRTCBaseSession, connectionFailedForUser userID: NSNumber) {
}
 
/**
 *  Called when session connection state changed for a specific user.
 *
 *  @param session QBRTCSession instance
 *  @param state   state - @see QBRTCConnectionState
 *  @param userID  ID of user
 */
func session(_ session: QBRTCBaseSession, didChange state: QBRTCConnectionState, forUser userID: NSNumber) {
}
/**
 *  Called by timeout with updated stats report for user ID.
 *
 *  @param session QBRTCSession instance
 *  @param report  QBRTCStatsReport instance
 *  @param userID  user ID
 *
 *  @remark Configure time interval with
 [QBRTCConfig setStatsReportTimeInterval:timeInterval].
 */
- (void)session:(__kindof QBRTCBaseSession *)session updatedStatsReport:(QBRTCStatsReport *)report forUserID:(NSNumber *)userID {
}

/**
 *  Called when session state has been changed.
 *
 *  @param session QBRTCSession instance
 *  @param state session state
 *
 *  @discussion Use this to track a session state.
 As SDK 2.3 introduced states for session,
 you can now manage your own states based on this.
 */
- (void)session:(__kindof QBRTCBaseSession *)session didChangeState:(QBRTCSessionState)state {
}

/**
 *  Called when received remote audio track from user.
 *
 *  @param audioTrack QBRTCAudioTrack instance
 *  @param userID     ID of user
 */
- (void)session:(__kindof QBRTCBaseSession *)session receivedRemoteAudioTrack:(QBRTCAudioTrack *)audioTrack fromUser:(NSNumber *)userID {
}

/**
 *  Called when received remote video track from user.
 *
 *  @param videoTrack QBRTCVideoTrack instance
 *  @param userID     ID of user
 */
- (void)session:(__kindof QBRTCBaseSession *)session receivedRemoteVideoTrack:(QBRTCVideoTrack *)videoTrack fromUser:(NSNumber *)userID {
}

/**
 *  Called when connection is closed for user.
 *
 *  @param session QBRTCSession instance
 *  @param userID  ID of user
 */
- (void)session:(__kindof QBRTCBaseSession *)session connectionClosedForUser:(NSNumber *)userID {
}

/**
 *  Called when connection is initiated with user.
 *
 *  @param session QBRTCSession instance
 *  @param userID  ID of user
 */
- (void)session:(__kindof QBRTCBaseSession *)session startedConnectingToUser:(NSNumber *)userID {
}

/**
 *  Called when connection is established with user.
 *
 *  @param session QBRTCSession instance
 *  @param userID  ID of user
 */
- (void)session:(__kindof QBRTCBaseSession *)session connectedToUser:(NSNumber *)userID {
}

/**
 *  Called when disconnected from user.
 *
 *  @param session QBRTCSession instance
 *  @param userID  ID of user
 */
- (void)session:(__kindof QBRTCBaseSession *)session disconnectedFromUser:(NSNumber *)userID {
}

/**
 *  Called when connection failed with user.
 *
 *  @param session QBRTCSession instance
 *  @param userID  ID of user
 */
- (void)session:(__kindof QBRTCBaseSession *)session connectionFailedForUser:(NSNumber *)userID {
}

/**
 *  Called when session connection state changed for a specific user.
 *
 *  @param session QBRTCSession instance
 *  @param state   state - @see QBRTCConnectionState
 *  @param userID  ID of user
 */
- (void)session:(__kindof QBRTCBaseSession *)session didChangeConnectionState:(QBRTCConnectionState)state forUser:(NSNumber *)userID {
}

Conference client delegate protocol methods

All protocol methods below are conference client-specific, optional, and have their own explanation inlined.

/**
 *  Called when session was created on server.
 *
 *  @param session QBRTCConferenceSession instance
 *
 *  @discussion When this method is called, session
 instance that was already created by QBRTCConferenceClient
 *  will be assigned valid session ID from server.
 *
 *  @see QBRTCConferenceSession, QBRTCConferenceClient
 */
func didCreateNewSession(_ session: QBRTCConferenceSession?) {
}

/**
 *  Called when join to session is performed and
 acknowledged by server.
 *
 *  @param session QBRTCConferenceSession instance
 *  @param chatDialogID chat dialog ID
 *  @param publishersList array of user IDs,
 that are currently publishers
 *
 *  @see QBRTCConferenceSession
 */
func session(_ session: QBRTCConferenceSession?, didJoinChatDialogWithID chatDialogID: String?, publishersList: [NSNumber]) {
}

/**
 *  Called when new publisher did join.
 *
 *  @param session QBRTCConferenceSession instance
 *  @param userID new publisher user ID
 *
 *  @see QBRTCConferenceSession
 */
func session(_ session: QBRTCConferenceSession?, didReceiveNewPublisherWithUserID userID: NSNumber?) {
}

/**
 *  Called when publisher did leave.
 *
 *  @param session QBRTCConferenceSession instance
 *  @param userID publisher that left user ID
 *
 *  @see QBRTCConferenceSession
 */
func session(_ session: QBRTCConferenceSession?, publisherDidLeaveWithUserID userID: NSNumber?) {
}

/**
 *  Called when session did receive error from server.
 *
 *  @param session QBRTCConferenceSession instance
 *  @param error received error from server
 *
 *  @note Error doesn't necessarily means that session
 is closed. Can be just a minor error that can be fixed/ignored.
 *
 *  @see QBRTCConferenceSession
 */
func session(_ session: QBRTCConferenceSession!, didReceiveError error: Error!) {
}

/**
 *  Called when slowlink was received.
 *
 *  @param session  QBRTCConferenceSession instance
 *  @param uplink   whether the issue is uplink or not
 *  @param nacks    number of nacks
 *
 *  @discussion this callback is triggered when serber
 reports trouble either sending or receiving media on the
 *  specified connection, typically as a consequence of
 too many NACKs received from/sent to the user in the last
 *  second: for instance, a slowLink with uplink=true
 means you notified several missing packets from server,
 *  while uplink=false means server is not receiving
 all your packets.
 *
 *  @note useful to figure out when there are problems on
 the media path (e.g., excessive loss), in order to
 *  possibly react accordingly (e.g., decrease the bitrate if
 most of our packets are getting lost).
 *
 *  @see QBRTCConferenceSession
 */
func session(_ session: QBRTCConferenceSession!, didReceiveSlowlinkWithUplink uplink: Bool, nacks: NSNumber!) {
}

/**
 *  Called when media receiving state was changed on server.
 *
 *  @param session QBRTCConferenceSession instance
 *  @param mediaType media type
 *  @param receiving whether media is receiving by server
 *
 *  @see QBRTCConferenceSession, QBRTCConferenceMediaType
 */
func session(_ session: QBRTCConferenceSession!, didChangeMediaStateWith mediaType: QBRTCConferenceMediaType, receiving: Bool) {
}

/**
 *  Session did initiate close request.
 *
 *  @param session QBRTCConferenceSession instance
 *
 *  @discussion 'sessionDidClose:withTimeout:' will be
 called after server will close session with callback
 *
 *  @see QBRTCConferenceSession
 */
func sessionWillClose(_ session: QBRTCConferenceSession?) {
}

/**
 *  Called when session was closed completely on server.
 *
 *  @param session QBRTCConferenceSession instance
 *  @param timeout whether session was closed due to timeout on server
 *
 *  @see QBRTCConferenceSession
 */
func sessionDidClose(_ session: QBRTCConferenceSession?, withTimeout timeout: Bool) {
}
/**
 *  Called when session was created on server.
 *
 *  @param session QBRTCConferenceSession instance
 *
 *  @discussion When this method is called, session
 instance that was already created by QBRTCConferenceClient
 *  will be assigned valid session ID from server.
 *
 *  @see QBRTCConferenceSession, QBRTCConferenceClient
 */
- (void)didCreateNewSession:(QBRTCConferenceSession *)session {
}

/**
 *  Called when join to session is performed and
 acknowledged by server.
 *
 *  @param session QBRTCConferenceSession instance
 *  @param chatDialogID chat dialog ID
 *  @param publishersList array of user IDs,
 that are currently publishers
 *
 *  @see QBRTCConferenceSession
 */
- (void)session:(QBRTCConferenceSession *)session didJoinChatDialogWithID:(NSString *)chatDialogID publishersList:(NSArray <NSNumber *> *)publishersLis {
}

/**
 *  Called when new publisher did join.
 *
 *  @param session QBRTCConferenceSession instance
 *  @param userID new publisher user ID
 *
 *  @see QBRTCConferenceSession
 */
- (void)session:(QBRTCConferenceSession *)session didReceiveNewPublisherWithUserID:(NSNumber *)userID {
}

/**
 *  Called when publisher did leave.
 *
 *  @param session QBRTCConferenceSession instance
 *  @param userID publisher that left user ID
 *
 *  @see QBRTCConferenceSession
 */
- (void)session:(QBRTCConferenceSession *)session publisherDidLeaveWithUserID:(NSNumber *)userID {
}

/**
 *  Called when session did receive error from server.
 *
 *  @param session QBRTCConferenceSession instance
 *  @param error received error from server
 *
 *  @note Error doesn't necessarily means that session
 is closed. Can be just a minor error that can be fixed/ignored.
 *
 *  @see QBRTCConferenceSession
 */
- (void)session:(QBRTCConferenceSession *)session didReceiveError:(NSError *)error {
}

/**
 *  Called when slowlink was received.
 *
 *  @param session  QBRTCConferenceSession instance
 *  @param uplink   whether the issue is uplink or not
 *  @param nacks    number of nacks
 *
 *  @discussion this callback is triggered when serber
 reports trouble either sending or receiving media on the
 *  specified connection, typically as a consequence of
 too many NACKs received from/sent to the user in the last
 *  second: for instance, a slowLink with uplink=true
 means you notified several missing packets from server,
 *  while uplink=false means server is not receiving
 all your packets.
 *
 *  @note useful to figure out when there are problems on
 the media path (e.g., excessive loss), in order to
 *  possibly react accordingly (e.g., decrease the bitrate if
 most of our packets are getting lost).
 *
 *  @see QBRTCConferenceSession
 */
- (void)session:(QBRTCConferenceSession *)session didReceiveSlowlinkWithUplink:(BOOL)uplink nacks:(NSNumber *)nacks {
    
}

/**
 *  Called when media receiving state was changed on server.
 *
 *  @param session QBRTCConferenceSession instance
 *  @param mediaType media type
 *  @param receiving whether media is receiving by server
 *
 *  @see QBRTCConferenceSession, QBRTCConferenceMediaType
 */
- (void)session:(QBRTCConferenceSession *)session didChangeMediaStateWithType:(QBRTCConferenceMediaType)mediaType receiving:(BOOL)receiving {
}

/**
 *  Session did initiate close request.
 *
 *  @param session QBRTCConferenceSession instance
 *
 *  @discussion 'sessionDidClose:withTimeout:' will be
 called after server will close session with callback
 *
 *  @see QBRTCConferenceSession
 */
- (void)sessionWillClose:(QBRTCConferenceSession *)session {
}

/**
 *  Called when session was closed completely on server.
 *
 *  @param session QBRTCConferenceSession instance
 *  @param timeout whether session was closed due to timeout on server
 *
 *  @see QBRTCConferenceSession
 */
- (void)sessionDidClose:(QBRTCConferenceSession *)session withTimeout:(BOOL)timeout {
}

Conference client interface

QBRTCConferenceClient is a singleton-based class that is used to create and operate with conference sessions. It has an observer (delegates) manager which can be activated/deactivated with two simple methods:

/**
 *  Add delegate to the observers list.
 *
 *  @param delegate delegate that conforms to
 QBRTCConferenceClientDelegate protocol
 *
 *  @see QBRTCConferenceClientDelegate
 */
QBRTCConferenceClient.instance().add(self)

/**
 *  Remove delegate from the observers list.
 *
 *  @param delegate delegate that conforms to
 QBRTCConferenceClientDelegate protocol
 *
 *  @see QBRTCConferenceClientDelegate
 */
QBRTCConferenceClient.instance().remove(self)
/**
 *  Add delegate to the observers list.
 *
 *  @param delegate delegate that conforms to
 QBRTCConferenceClientDelegate protocol
 *
 *  @see QBRTCConferenceClientDelegate
 */
[[QBRTCConferenceClient instance] addDelegate:self];
 
/**
 *  Remove delegate from the observers list.
 *
 *  @param delegate delegate that conforms to
 QBRTCConferenceClientDelegate protocol
 *
 *  @see QBRTCConferenceClientDelegate
 */
[[QBRTCConferenceClient instance] removeDelegate:self];

The delegate should conform to the QBRTCConferenceClientDelegate protocol, which is inherited from the base client delegate. In order to create a new conference session, use the method below:

/**
 *  Send create session request.
 *
 *  @note Returns session without ID. When session will be created on server
 *  ID will be assigned and session will be returned in 'didCreateNewSession()' callback.
 *
 *  @see QBRTCConferenceClientDelegate
 *
 *  @param chatDialogID chat dialog ID
 */
let session = QBRTCConferenceClient.instance().createSession(withChatDialogID: chatDialogID, conferenceType: QBRTCConferenceType.video)
/**
 *  Send create session request.
 *
 *  @note Returns session without ID. When session will be created on server
 *  ID will be assigned and session will be returned in 'didCreateNewSession:' callback.
 *
 *  @see QBRTCConferenceClientDelegate
 *
 *  @param chatDialogID chat dialog ID
 */
// creating session
QBRTCConferenceSession *session = [[QBRTCConferenceClient instance] createSessionWithChatDialogID:self.chatDialog.ID conferenceType: QBRTCConferenceTypeVideo];

This method will create the session locally first, without a session ID, until the server will perform a didCreateNewSession() callback in QBRTCConferenceClientDelegate protocol, where the session ID will be assigned and the session will receive its QBRTCSessionStateNew state. After that, you can join or leave it. The conference session is explained below.

Conference session

QBRTCConferenceSession is inherited from the base session class and has all of its basics such as state, currentUserID, localMediaStream as well as the ability to get remote audio and video tracks for specific user IDs.

/**
 *  Remote audio track with opponent user ID.
 *
 *  @param userID opponent user ID
 *
 *  @return QBRTCAudioTrack audio track instance
 */
let audioTrack = session.remoteAudioTrack(withUserID: userID)

/**
 *  Remote video track with opponent user ID.
 *
 *  @param userID opponent user ID
 *
 *  @return QBRTCVideoTrack video track instance
 */
let remoteVideoTraсk = session.remoteVideoTrack(withUserID: NSNumber(value: userID))
/**
 *  Remote audio track with opponent user ID.
 *
 *  @param userID opponent user ID
 *
 *  @return QBRTCAudioTrack audio track instance
 */
QBRTCAudioTrack *audioTrack = [self.session remoteAudioTrackWithUserID:@(user.ID)];

/**
 *  Remote video track with opponent user ID.
 *
 *  @param userID opponent user ID
 *
 *  @return QBRTCVideoTrack video track instance
 */
QBRTCVideoTrack *remoteVideoTraсk = [self.session remoteVideoTrackWithUserID:opponentID];

It also has the ability to get a connection state for a specific user ID if their connection is opened.

/**
 *  Connection state for opponent user ID.
 *
 *  @param userID opponent user ID
 *
 *  @return QBRTCConnectionState connection state for opponent user ID
 */
let connectionState = session.connectionState(forUser: userID)
/**
 *  Connection state for opponent user ID.
 *
 *  @param userID opponent user ID
 *
 *  @return QBRTCConnectionState connection state for opponent user ID
 */
QBRTCConnectionState connectionState = [self.session connectionStateForUser:userID];

See a QBRTCBaseSession class for more inline documentation. As for conference-specific methods, the conference session ID is NSNumber. Each conference session is tied to a specific QuickBlox dialog ID (NSString).

Join video room

A QBRTCConferenceSession also has a publishers list property. But the publishers list will be only valid if you call joinAsPublisher() method allowing to join the session as a publisher using method below.

/**
 *  Perform join room as publisher.
 *
 *  @discussion 'session:didJoinChatDialogWithID:publishersList:' will be called upon successful join.
 *
 *  @see QBRTCConferenceClientDelegate
 */
session.joinAsPublisher()
/**
 *  Perform join room as publisher.
 *
 *  @discussion 'session:didJoinChatDialogWithID:publishersList:' will be called upon successful join.
 *
 *  @see QBRTCConferenceClientDelegate
 */
[self.session joinAsPublisher];

This method joins the session and will publish your feed making you an active publisher in the room. Everyone in the room will be able to subscribe and receive your feed.

📘

joinAsPublisher() can be used only when the session has a valid session ID, e.g. is created on the server and notified to you with didCreateNewSession() callback from QBRTCConferenceClientDelegate protocol.

Subscribe/Unsubscribe

You can subscribe and unsubscribe from publishers using the methods below.

📘

You do not need to be joined as a publisher in order to perform subscription-based operations in the session.

/**
 *  Subscribe to publisher's with user ID feed.
 *
 *  @param userID active publisher's user ID
 *
 *  @discussion If you want to receive publishers feeds, you need to subscribe to them.
 *
 *  @note User must be an active publisher.
 */
session.subscribeToUser(withID: userID)

/**
 *  Unsubscribe from publisher's with user ID feed.
 *
 *  @param userID active publisher's user ID
 *
 *  @discussion Do not need to be used when publisher did leave room, in that case unsibscribing will be performing automatically. Use if you need to unsubscribe from active publisher's feed.
 *
 *  @note User must be an active publisher.
 */
session.unsubscribeFromUser(withID: userID)
/**
 *  Subscribe to publisher's with user ID feed.
 *
 *  @param userID active publisher's user ID
 *
 *  @discussion If you want to receive publishers feeds, you need to subscribe to them.
 *
 *  @note User must be an active publisher.
 */
[self.session subscribeToUserWithID:userID];

/**
 *  Unsubscribe from publisher's with user ID feed.
 *
 *  @param userID active publisher's user ID
 *
 *  @discussion Do not need to be used when publisher did leave room, in that case unsibscribing will be performing automatically. Use if you need to unsubscribe from active publisher's feed.
 *
 *  @note User must be an active publisher.
 */
[self.session unsubscribeFromUserWithID:userID];

📘

These methods can also be used only when the session has a valid session ID, e.g. is created on the server and is notified to you with didCreateNewSession() callback from QBRTCConferenceClientDelegate protocol.

Mute local audio

Mute the audio by calling the localMediaStream.audioTrack.enabled() method. Using this method, we can tell SDK to send/not send audio data from a local peer in the specified WebRTC session.

self.session?.localMediaStream.audioTrack.enabled = !self.session?.localMediaStream.audioTrack.enabled
self.session.localMediaStream.audioTrack.enabled ^= 1;

Mute remote audio

You can always get remote audio tracks for a specific user ID in the call using the above-specified QBRTCSession methods (assuming that they are existent). You can also mute remote media tracks on your side by changing the value of enabled property for a specific remote media track.

let remoteAudioTrack = self.session?.remoteAudioTrack(withUserID: 24450) // audio track for user 24450
//mute
remoteAudioTrack.enabled = false
QBRTCAudioTrack *remoteAudioTrack = [self.session remoteAudioTrackWithUserID:@(24450)]; // audio track for user 24450
//mute
remoteAudioTrack.enabled = NO;

Disable local video

Turn off the video by calling localVideoTrack.setEnabled(). Using this method, we can tell SDK not to send video data from a local peer in the specified session.

self.session?.localMediaStream.videoTrack.enabled = !self.session?.localMediaStream.videoTrack.enabled
self.session.localMediaStream.videoTrack.enabled ^=1;

Disable remote video

Turn off the video by calling localVideoTrack.setEnabled(). Using this method, we can tell SDK not to send video data from a remote peer in the specified session.

let remoteVideoTraсk = session.remoteVideoTrack(withUserID: NSNumber(value: userID))
//mute
remoteVideoTraсk.enabled = false
QBRTCVideoTrack *remoteVideoTraсk = [self.session remoteVideoTrackWithUserID:opponentID];
//mute
remoteVideoTraсk.enabled = NO;

Leave video room

To leave the session, you can perform the leave() method.

/**
 *  Leave chat room and close session.
 *
 *  @discussion 'sessionWillClose:' will be called when all connection are closed, 'sessionDidClose:withTimeout:' will be called when session will be successfully closed by server.
 */
session.leave()
/**
 *  Leave chat room and close session.
 *
 *  @discussion 'sessionWillClose:' will be called when all connection are closed, 'sessionDidClose:withTimeout:' will be called when session will be successfully closed by server.
 */
[self.session leave];

📘

This method can be called in any state of the session and will always close it no matter what.

Camera resolution

It's possible to set custom video resolution using QBRTCVideoFormat.

let customVideoFormat: QBRTCVideoFormat = QBRTCVideoFormat.init(width: 950, height: 540, frameRate: 30, pixelFormat: .format420f) 
let cameraCapture = QBRTCCameraCapture(videoFormat: customVideoFormat, position: cameraPosition)
QBRTCVideoFormat *customVideoFormat = [QBRTCVideoFormat videoFormatWithWidth:950 height:540 frameRate:30 pixelFormat:QBRTCPixelFormat420f]; 
QBRTCCameraCapture *cameraCapture = [[QBRTCCameraCapture alloc] initWithVideoFormat:customVideoFormat position:cameraPosition];
ParametersDescription
widthVideo width. Default: 640.
heightVideo hight. Default: 480.
frameRateVideo frames per second. Default: 30.
pixelFormatVideo pixel format. Default: QBRTCPixelFormat420f.

You can also get a list of available resolution formats using formats(with:) method and set a needed one from the list.

var formats = QBRTCCameraCapture.formats(with: cameraPosition)
NSArray<QBRTCVideoFormat *> *videoFormats = [QBRTCCameraCapture formatsWithPosition:cameraPosition]; // Array of possible QBRTCVideoFormat video formats for requested device

What’s Next