Participant Class Methods - iOS
Methods marked async throws must be called with try await from an async context, such as a Task. When a call is refused or fails, it throws a VideoSDKError. Read its code, name and message.
Task {
do {
try await participant.disableMic()
} catch let error as VideoSDKError {
print("disableMic failed: \(error.code) \(error.name) \(error.message)")
} catch {
print("disableMic failed: \(error)")
}
}
Every async throws method except captureImage() throws ERROR_ACTION_PERFORMED_BEFORE_ROOM_JOINED (3035) when it is called before the room is joined or after you leave, and ERROR_ROOM_RECONNECTING (3065) while the room is reconnecting. The same error is also sent to onError(), so don't show it to the user twice.
On an agent participant (isAgent() returns true), enableMic(), disableMic(), enableCam(), disableCam(), setQuality(), captureImage() and getShareStats() throw ERROR_ACTION_NOT_SUPPORTED (3068).
enableCam()
enableCam()is used to ask a remote participant to turn on their webcam. It isasync throws.- It works only on remote participants. To turn on your own webcam, use
enableCam()of the Room class.
Events associated with enableCam():
-
First the participant will get a callback on
onWebcamRequested()and once the participant accepts the request, webcam will be enabled. -
Every participant that receives the participant's video will get an
onStreamEnabled()event with the stream object.
Returns
Void
disableCam()
disableCam()is used to turn off the webcam of a remote participant. It isasync throws.- The webcam turns off right away. The participant is not asked first.
- It works only on remote participants. To turn off your own webcam, use
disableCam()of the Room class.
Events associated with disableCam():
- Every participant that receives the participant's video will get an
onStreamDisabled()event with the stream object.
Returns
Void
enableMic()
enableMic()is used to ask a remote participant to turn on their mic. It isasync throws.- It works only on remote participants. To turn on your own mic, use
unmuteMic()of the Room class.
Events associated with enableMic():
-
First the participant will get a callback on
onMicRequested()and once the participant accepts the request, mic will be enabled. -
Every participant that receives the participant's audio will get an
onStreamEnabled()event with the stream object.
Returns
Void
disableMic()
disableMic()is used to turn off the mic of a remote participant. It isasync throws.- The mic turns off right away. The participant is not asked first.
- It works only on remote participants. To turn off your own mic, use
muteMic()of the Room class.
Events associated with disableMic():
- Every participant that receives the participant's audio will get an
onStreamDisabled()event with the stream object.
Returns
Void
setQuality()
setQuality()is used to set the quality of the participant's video stream that this device receives. It isasync throws.- It does nothing for the local participant, or when
videoQualityalready has the requested value.
Parameters
quality:VideoQuality(.low|.medium|.high)
Throws
ERROR_ACTION_NOT_SUPPORTED(3068) when this device receives no video from the participant's webcam, for example while it is off.
Returns
Void
Example
Task {
do {
try await participant.setQuality(.low)
} catch let error as VideoSDKError {
print("setQuality failed: \(error.code) \(error.name)")
} catch {
print("setQuality failed: \(error)")
}
}
setScreenShareQuality()
setScreenShareQuality()is used to set the quality of the participant's screen share that this device receives. It isasync throws.- It changes only the screen share. The webcam video keeps its quality.
Parameters
quality:VideoQuality(.low|.medium|.high)
Throws
ERROR_ACTION_NOT_SUPPORTED(3068) when this device receives no screen share from the participant.
Returns
Void
setViewPort()
setViewPort()is used to tell the SDK the size at which the participant's webcam video is shown, so that the server sends a quality that fits it. It isasync throws.- Call it when the view is laid out, and again when it is resized. It applies to the webcam video, not to the screen share.
Parameters
width:Int- the width of the view, in pixels (not points).height:Int- the height of the view, in pixels (not points).
Throws
- A
VideoSDKErrorwhen this device receives no video from the participant's webcam, for example while it is off. It also throws for the local participant, so call it only for remote participants.
Returns
Void
Example
let scale = videoView.traitCollection.displayScale
let width = Int(videoView.bounds.width * scale)
let height = Int(videoView.bounds.height * scale)
Task {
do {
try await participant.setViewPort(width: width, height: height)
} catch {
print("setViewPort failed: \(error)")
}
}
setQuality(), setScreenShareQuality() and setViewPort() choose among the layers the participant publishes. If the participant publishes a single layer, for example with multiStream set to false, these calls can't change what you receive. To know more about layers, see Simulcast.
consumeMicStreams()
consumeMicStreams()is used to start receiving the participant's audio on this device. It isasync throws.- Takes effect only when the room was created with
autoConsumeset tofalse. SeecreateRoom(). In such a room, remote audio and video are not received until you ask for them. Also use it to receive the audio again afterstopConsumingMicStreams(). - It changes only what this device receives. The participant is not asked.
- Call it after the room is joined. Participants who were already in the room are reported through
onParticipantJoined()beforeonRoomJoined(), so start receiving them fromonRoomJoined().
Events associated with consumeMicStreams():
- If the participant's mic is on, an
onStreamEnabled()event is triggered once their audio arrives.
Returns
Void
Example
In this example, hasJoined is a Bool property of your view controller that starts as false.
extension RoomViewController: RoomEventListener {
func onRoomJoined() {
hasJoined = true
// Participants who were already in the room
room?.participants.values.forEach { receiveMedia(of: $0) }
}
func onParticipantJoined(_ participant: Participant) {
// Participants who join later
if hasJoined {
receiveMedia(of: participant)
}
}
func receiveMedia(of participant: Participant) {
Task {
do {
try await participant.consumeMicStreams()
try await participant.consumeWebcamStreams()
} catch {
print("Could not receive media of \(participant.displayName): \(error)")
}
}
}
}
consumeWebcamStreams()
consumeWebcamStreams()is used to start receiving the participant's webcam video on this device. It isasync throws.- It works like
consumeMicStreams(), for video. Takes effect only when the room was created withautoConsumeset tofalse. Use it to receive a participant's video, or to receive it again afterstopConsumingWebcamStreams().
Events associated with consumeWebcamStreams():
- If the participant's webcam is on, an
onStreamEnabled()event is triggered once their video arrives.
Returns
Void
stopConsumingMicStreams()
stopConsumingMicStreams()is used to stop receiving the participant's audio on this device, which saves bandwidth. It isasync throws.- Takes effect only when the room was created with
autoConsumeset tofalse. - The participant is not muted, and everyone else still hears them. Call
consumeMicStreams()to receive the audio again.
Returns
Void
stopConsumingWebcamStreams()
stopConsumingWebcamStreams()is used to stop receiving the participant's webcam video on this device, which saves bandwidth. Use it, for example, for participants who are not on screen. It isasync throws.- Takes effect only when the room was created with
autoConsumeset tofalse. - The participant's webcam stays on for everyone else. Call
consumeWebcamStreams()to receive the video again.
Returns
Void
remove()
remove()is used to remove this participant from the room. It isasync throws.
Events associated with remove():
- The removed participant will receive an
onRoomLeft(reason:)event. - All other participants will receive an
onParticipantLeft(_:reason:)event of the Room class.
Returns
Void
pin()
pin()is used to pin this participant's webcam, screen share, or both. It isasync throws.- The pin state is shared with everyone in the room. Your app decides how to show a pinned participant.
Parameters
pinType:PinType(Optional) -.SHARE_AND_CAM(default),.CAMor.SHARE.
Events associated with pin():
- Every participant will receive an
onPinStateChanged()event.
Returns
Void
Example
Task {
do {
try await participant.pin(.CAM)
} catch {
print("pin failed: \(error)")
}
}
unpin()
unpin()is used to unpin this participant's webcam, screen share, or both. It isasync throws.
Parameters
pinType:PinType(Optional) -.SHARE_AND_CAM(default),.CAMor.SHARE.
Events associated with unpin():
- Every participant will receive an
onPinStateChanged()event.
Returns
Void
getAudioStats()
getAudioStats()will return an array which will contain details regarding the participant's critical audio metrics such as Jitter, Packet Loss etc.- It returns the values at the moment you call it, not averages over the whole time in the room.
Returns
Any?- an array of dictionaries ([[String: Any]]). Each entry contains:jitter: It represents the variation in packet arrival time, in milliseconds (ms).bitrate: It represents the bitrate of the stream which is being transmitted, in kbps.totalPackets: It represents the packets transmitted since the previous sample, not a running total.packetsLost: It represents the packets lost since the previous sample, not a running total.rtt: It represents the round-trip time between this device and the server, in milliseconds (ms).codec: It represents the codec used for the stream.
- It returns
nilbefore the room is joined, after you leave, or while the room is reconnecting. The array is empty when there is no audio stream, or no stats are available yet.
Example
if let audioStats = participant.getAudioStats() as? [[String: Any]],
let stats = audioStats.first {
print("Audio bitrate: \(stats["bitrate"] ?? 0) kbps")
}
getVideoStats()
getVideoStats()will return an array which will contain details regarding the participant's critical video metrics such as Jitter, Packet Loss etc.- It has one entry per video layer: one for each layer your own webcam sends, and one for the webcam video of a remote participant.
Returns
Any?- an array of dictionaries ([[String: Any]]). Each entry contains:jitter: It represents the variation in packet arrival time, in milliseconds (ms).bitrate: It represents the bitrate of the stream which is being transmitted, in kbps.totalPackets: It represents the packets transmitted since the previous sample, not a running total.packetsLost: It represents the packets lost since the previous sample, not a running total.rtt: It represents the round-trip time between this device and the server, in milliseconds (ms).codec: It represents the codec used for the stream.size: It is a dictionary containing thewidth,heightand, when known,framerateof the stream.
- It returns
nilbefore the room is joined, after you leave, or while the room is reconnecting. The array is empty when there is no webcam video, or no stats are available yet.
Example
if let videoStats = participant.getVideoStats() as? [[String: Any]] {
for layer in videoStats {
print("Video bitrate: \(layer["bitrate"] ?? 0) kbps, size: \(layer["size"] ?? [:])")
}
}
getShareStats()
getShareStats()will return an array which will contain details regarding the participant's critical screen share metrics such as Jitter, Packet Loss etc.- Call it with
try. It throws only on an agent participant.
Returns
Any?- an array of dictionaries ([[String: Any]]). Each entry contains:jitter: It represents the variation in packet arrival time, in milliseconds (ms).bitrate: It represents the bitrate of the stream which is being transmitted, in kbps.totalPackets: It represents the packets transmitted since the previous sample, not a running total.packetsLost: It represents the packets lost since the previous sample, not a running total.rtt: It represents the round-trip time between this device and the server, in milliseconds (ms).codec: It represents the codec used for the stream.size: It is a dictionary containing thewidth,heightand, when known,framerateof the stream.
- It returns
nilbefore the room is joined, after you leave, or while the room is reconnecting. The array is empty when the participant is not sharing their screen, or no stats are available yet.
Example
do {
if let shareStats = try participant.getShareStats() as? [[String: Any]] {
print("Screen share bitrate: \(shareStats.first?["bitrate"] ?? 0) kbps")
}
} catch {
print("getShareStats failed: \(error)")
}
getShareAudioStats()
getShareAudioStats()will return an array with the metrics of the audio shared along with the participant's screen share. The mic is not included; usegetAudioStats()for it.
Returns
Any?- an array of dictionaries ([[String: Any]]). Each entry contains the same values asgetAudioStats().- It returns
nilbefore the room is joined, after you leave, or while the room is reconnecting. The array is empty when the screen share has no audio.
Example
let shareAudioStats = participant.getShareAudioStats() as? [[String: Any]]
getTransportStats()
getTransportStats()will return the participant's network transport metrics: how much data flows in and out over their connection, for all their streams together.- It waits for a reply from the server, so call it off the main thread.
Returns
Any?- a dictionary ([String: Any]) containing:send: the data the participant sends.outgoingBitrate: the send bitrate, in kbps.totalSentBytes: the total bytes sent.
receive: the data the participant receives.incomingBitrate: the receive bitrate, in kbps.totalReceivedBytes: the total bytes received.
- It returns
nilbefore the room is joined, after you leave, while the room is reconnecting, or when the request fails.
Example
DispatchQueue.global(qos: .utility).async {
let transportStats = participant.getTransportStats() as? [String: Any]
let send = transportStats?["send"] as? [String: Any]
print("Sending at \(send?["outgoingBitrate"] ?? 0) kbps")
}
captureImage()
captureImage()is used to capture an image of the participant's current webcam video. It isasync throwsand returns the image as abase64string.- It works for the local participant, and for a remote participant whose webcam video this device receives.
Parameters
width:CGFloat(Optional) - the maximum width of the image, in pixels.height:CGFloat(Optional) - the maximum height of the image, in pixels.flash:CaptureFlash(Optional) -.ONlights the scene before the image is captured, which adds about half a second. It uses the camera's torch. On a front camera without a torch, it uses the screen flash set withVideoSDK.setScreenFlash(_:), such asWhiteOverlayScreenFlash. With neither, the image is captured unlit. It works only for the local participant. Default:.OFF.
The image is scaled down to fit within width and height, keeping its aspect ratio. It is never enlarged. Without them, the image has the size of the video.
Returns
String- the image as a base64-encoded JPEG.
Throws
ERROR_WEBCAM_NOT_ENABLED(3062) when the participant's webcam is off, or this device does not receive it.ERROR_CAPTURE_IMAGE_FAILED(3069) when the capture fails, whenflashis.ONfor a remote participant, or while another capture with flash is running. This error is also sent toonError().
Example
Task {
do {
let base64Image = try await participant.captureImage(width: 1280, height: 720)
if let data = Data(base64Encoded: base64Image) {
imageView.image = UIImage(data: data)
}
} catch {
print("Capture failed: \(error)")
}
}
To light the scene, pass flash. For front cameras without a torch, set a screen flash first:
VideoSDK.setScreenFlash(WhiteOverlayScreenFlash(window: view.window))
Task {
do {
let base64Image = try await room.localParticipant.captureImage(flash: .ON)
print("Captured image: \(base64Image.count) characters")
} catch {
print("Capture failed: \(error)")
}
}
addEventListener()
addEventListener()is used to add a listener that receives the participant's events.- Add it to each participant, for example in
onParticipantJoined(), and toroom.localParticipantfor your own streams. - The participant holds the listener weakly. Keep a strong reference to it, for example by using your view controller as the listener.
- Streams the participant already has are not reported again. Read
streamsfor those.
Parameters
listener:ParticipantEventListener
Returns
Void
Example
extension RoomViewController: RoomEventListener {
func onParticipantJoined(_ participant: Participant) {
participant.addEventListener(self)
}
}
removeEventListener()
removeEventListener()is used to remove a listener that was added withaddEventListener().
Parameters
listener:ParticipantEventListener
Returns
Void
Example
participant.removeEventListener(self)
removeAllEventListeners()
removeAllEventListeners()is used to remove all the listeners of this participant.
Returns
Void
Example
participant.removeAllEventListeners()
Got a Question? Ask us on discord

