The iOS SDK includes tools for monitoring session quality, running pre-call diagnostics, making
outbound calls, controlling session behaviour, and sharing logs with EnableX engineering. Use
these tools to build production-grade apps and diagnose issues quickly.
Live Media Statistics
During a live session, you often need visibility into how your streams are actually performing
— not just whether they are connected, but what resolution they are publishing at, how much
bandwidth they are consuming, and how much bandwidth is available. The
enableStats: method on EnxRoom gives you exactly this: a real-time,
periodic feed of statistics for every stream in the room.
Once you call enableStats:YES, the SDK begins collecting metrics for all published
and subscribed streams and delivers them to your delegate at regular intervals. The data includes
publishing resolution, publisher bandwidth, receiver resolution, receiver bandwidth consumed,
and available bandwidth. Call enableStats:NO to stop receiving updates.
Detail
Value
Class
EnxRoom
Method
-(void)enableStats:(BOOL)isEnabled
Delegate Methods
Delegate
Description
didAcknowledgeStats:
ACK when stats subscription is enabled or disabled.
didReceiveStats:
Fires periodically with an array of stats for all streams.
Per-Player Stats
In addition to room-level stats, you can receive statistics scoped to a single stream's player
view. This is useful when you want to display per-tile quality indicators in your UI rather than
processing the full room-level array. You must enable room-level stats first — per-player stats
layer on top of them, they do not work independently.
Call enablePlayerStats: on the EnxPlayerView instance for the stream
you want to monitor. The didPlayerStats: delegate fires with stats specific to that
player.
Detail
Value
Class
EnxPlayerView
Method
-(void)enablePlayerStats:(BOOL)isEnabled
Prerequisite
Room-level stats must be enabled first via enableStats:YES
Delegate
didPlayerStats: — stats for that specific player
Error Codes
Code
Description
5075
Repeated subscription while previous request is in process.
5076
Repeated unsubscription while previous request is in process.
5077
Already subscribed to stats.
5078
Unsubscribing without having subscribed first.
5079
Cannot unsubscribe while subscription is in process.
5080
Unsubscription already in process.
// Enable room-level stats
enxRoom.enableStats(true)
func didAcknowledgeStats(_ data: [Any]?) {
// Stats subscription toggled successfully
}
func didReceiveStats(_ data: [Any]?) {
// data: array of stream stats objects
// Each object includes resolution, bandwidth, available bandwidth
}
// Enable per-player stats (room-level must be enabled first)
enxPlayer.enablePlayerStats(true)
func didPlayerStats(_ data: [Any]?) {
// Stats for this specific stream player
}
// Enable room-level stats
[enxRoom enableStats:YES];
-(void)didAcknowledgeStats:(NSArray *)data {
// Stats subscription toggled successfully
}
-(void)didReceiveStats:(NSArray *)data {
// data: array of stream stats objects
// Each object includes resolution, bandwidth, available bandwidth
}
// Enable per-player stats (room-level must be enabled first)
[enxPlayer enablePlayerStats:YES];
-(void)didPlayerStats:(NSArray *)data {
// Stats for this specific stream player
}
Talker and Noise Notification
Note. Available from iOS SDK v1.9.5 and later.
When you need to know in real time who is speaking and who is generating background noise,
subscribe to talker notifications. The SDK analyses audio levels continuously and fires delegate
events whenever the set of speaking or noisy participants changes.
The talker list produced by this subscription can be longer than the Active Talker list shown in
the video grid, because it is not capped by the room's max_active_talkers setting.
This makes it well-suited for building speaker-highlight UIs — for example, putting a coloured
border around anyone who is currently speaking — and for debugging audio issues in a session.
Each didTalkerNotification: callback carries two arrays inside the data object.
The speech array lists users who are currently speaking — each entry includes a
clientId and a speechType indicating intensity
(high, medium, or low). The noise array
lists users generating background noise, identified by clientId only.
Error Codes
Code
Description
5128
Repeated subscription while previous request is in process.
5129
Repeated unsubscription while previous request is in process.
Voice Activity Detection (VAD) analyses your local audio track in real time and fires delegate
callbacks the moment speech or noise is detected. Unlike talker notifications — which are
server-side and cover all participants — VAD runs locally and reports on the device's own
microphone input only.
Use VAD to build microphone level indicators that animate in response to actual audio activity,
or to implement auto-mute and auto-unmute triggers that react to the user starting or stopping
speech. Call enableVAD:YES to start detection and enableVAD:NO to
stop.
Detail
Value
Class
EnxRoom
Method
-(void)enableVAD:(BOOL)isEnabled
Delegate Methods
Delegate
Description
vadDidDetectSpeech:
Fires when speech is detected. Returns a confidence score from 0.0 to 1.0 — higher values indicate greater confidence.
vadDidDetectNoise:
Fires when noise is detected. Returns an enumerated noise type string.
Possible noise type values reported by vadDidDetectNoise:: Background Noise,
Static Noise, Music, Audio Noise, Traffic Noise.
enxRoom.enableVAD(true)
func vadDidDetectSpeech(_ confidence: Float) {
// confidence: 0.0 to 1.0
// Use to drive a mic-level indicator
}
func vadDidDetectNoise(_ noiseType: String?) {
// noiseType examples: "Background Noise", "Traffic Noise"
}
[enxRoom enableVAD:YES];
-(void)vadDidDetectSpeech:(Float32)confidence {
// confidence: 0.0 to 1.0
// Use to drive a mic-level indicator
}
-(void)vadDidDetectNoise:(NSString *)noiseType {
// noiseType examples: "Background Noise", "Traffic Noise"
}
Pre-Call Diagnostics
Note. Available from iOS SDK v1.9.6 and later. Requires iOS 13 or higher.
Camera, Microphone, and Bandwidth test groups are not available in SDK v1.9.6.
Rather than discovering connectivity or hardware issues during a live session, you can run a
full suite of pre-call tests before the session begins. Pre-call diagnostics probe your
microphone, camera, network connectivity, throughput, bandwidth, and signalling layer — giving
you a complete picture of whether the device and network are ready for a call.
Tests are grouped by category and execute asynchronously. The SDK fires
didClientDiagnosisStatus: after each individual test case completes, giving you
intermediate results as they arrive. When every test in the suite is finished,
didClientDiagnosisFinished: fires with the complete report. You can also stop
tests mid-run by passing stop: YES in a second call to
clientDiagnostics:.
Outbound calling lets you dial a PSTN phone number or SIP URI from within a live session.
The called party receives a regular phone call on their device; once they answer, they are
bridged directly into the video session. This is useful for inviting external participants who
do not have the app, or for integrating with legacy telephony systems via SIP.
You can dial a single number or up to five numbers simultaneously. Each outgoing call fires
repeated dial state events — initiated, calling,
connecting, connected, terminated — so you can track the
call lifecycle and update your UI accordingly.
Your CLI (Calling Line ID). Must match your purchased or shared number in the EnableX portal.
dialOptions.name
String
Display name shown to the called party.
dialOptions.early_media
Boolean
When true, plays a ringer inside the room while the call is dialling. Default: false.
dialOptions.silent_join
Boolean
When true, holds the caller outside the room until they answer. Default: true.
Note. The dialOptions parameters (early_media and
silent_join) are available from iOS SDK 2.1.3 and later.
early_media and silent_join cannot be used together.
Important. The callerId must exactly match the PSTN number
purchased or configured as a shared number in the EnableX portal. A mismatch causes error
1142 (CLI mismatch) and the call will not be placed.
Delegate Methods
Delegate
Description
room:didOutBoundCallInitiated:
Fires for the call initiator to confirm the call has started dialling.
room:didDialStateEvents:
Fires repeatedly with state updates: initiated → calling → connecting → connected → terminated.
Error Codes
Code
Description
1141
Outbound call already in process.
1142
CLI mismatch — callerId does not match a configured number.
5095
Invalid phone number format.
Cancel an Outbound Call
Available from iOS SDK 2.1.3 and later. Call cancelOutboundCall: to cancel a
dialling or ringing outbound call before it is answered. The
room:didOutBoundCallCancel: delegate fires on success.
Detail
Value
Method
-(void)cancelOutboundCall:(NSString *)number
Delegate
room:didOutBoundCallCancel:
Send DTMF
Available from iOS SDK v2.3.16 and later. After a PSTN call connects and the called party's
system presents an IVR, use sendDTMF:digits: to send digit presses into the call.
This is necessary when the connected party is an automated system that expects keypad input —
for example, navigating a menu or entering a conference PIN.
Use setAudioOnlyMode: to toggle between audio-only and full audio+video within a
live session. When audio-only mode is active, you neither send nor receive video. Your audio
stream continues uninterrupted, and other participants in the room are not affected. This is
useful on poor network connections where video cannot be sustained, or when the user explicitly
opts out of video.
Detail
Value
Class
EnxRoom
Method
-(void)setAudioOnlyMode:(BOOL)check
Error Code
Description
5051
Previous audio-only request is still in process.
5052
Already in audio-only mode.
5053
Already in audio+video mode.
5054
Previous audio-video request is still in process.
Adjust Layout
When you use activeviews: "view" in connect(), the SDK manages a
UIView grid internally. If the parent container changes size — due to device
rotation or a dynamic layout change — the grid does not automatically refit. Call
adjustLayout to tell the SDK to recalculate and reposition all player tiles to
match the current container dimensions.
Detail
Value
Class
EnxRoom
Method
-(void)adjustLayout
enxRoom.adjustLayout()
[enxRoom adjustLayout];
Background and Foreground Handling
iOS suspends camera capture when an app moves to the background. If you do not handle this
explicitly, your published video track will freeze on other participants' screens until the app
returns to the foreground. Use the two lifecycle methods below to stop and resume local video
in sync with the app lifecycle.
Call stopVideoTracksOnApplicationBackground: in your
applicationDidEnterBackground: handler to stop publishing local video. Call
startVideoTracksOnApplicationForeground: in
applicationWillEnterForeground: to resume it. Pass YES to each.
Resume publishing local video when the app returns to the foreground.
// In applicationDidEnterBackground:
room.stopVideoTracksOnApplicationBackground(true)
// In applicationWillEnterForeground:
room.startVideoTracksOnApplicationForeground(true)
// In applicationDidEnterBackground:
[room stopVideoTracksOnApplicationBackground:YES];
// In applicationWillEnterForeground:
[room startVideoTracksOnApplicationForeground:YES];
Update Stream Configuration
Available from iOS SDK 1.5.6 and later. You can reconfigure the bandwidth limits on an active
local or remote stream without disconnecting or republishing. This is useful when network
conditions change mid-session and you want to throttle the stream to prevent dropped frames or
buffering without ending the call.
Detail
Value
Class
EnxStream
Method
-(void)updateConfiguration:(NSDictionary *)data
The data dictionary accepts the following bandwidth keys (all values as strings,
in kbps): maxVideoBW, minVideoBW, maxAudioBW,
minAudioBW.
Error Code
Description
5113
Invalid JSON — the data dictionary is malformed.
5114
Canvas streaming is active — configuration cannot be updated.
You can take a snapshot of the current video frame from any EnxPlayerView —
whether it is displaying your own local stream or a remote participant's stream. The snapshot
is returned as a UIImage, which you can display in your UI, save to the photo
library, or upload to a server.
Set the delegate on the EnxPlayerView instance, then call
captureScreenShot. The didCapturedView: delegate fires with the
captured image.
Detail
Value
Class
EnxPlayerView
Method
captureScreenShot
Delegate
didCapturedView: — receives a UIImage of the current frame
// Set delegate and capture
enxPlayer.delegate = self
enxPlayer.captureScreenShot()
func didCapturedView(_ snapShot: UIImage?) {
// snapShot is the captured UIImage frame
if let image = snapShot {
UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil)
}
}
// Set delegate and capture
enxPlayer.delegate = self;
[enxPlayer captureScreenShot];
-(void)didCapturedView:(UIImage *)snapShot {
// snapShot is the captured UIImage frame
UIImageWriteToSavedPhotosAlbum(snapShot, nil, nil, nil);
}
Logging
When investigating a connection problem or an intermittent failure, raw console output is often
not enough — you need the SDK's internal log stream, which captures ICE negotiation steps,
connection events, and error details that are not surfaced through delegates. The
EnxLogger class lets you start capturing this log data, and
postClientLogs uploads the most recent 200 KB directly to EnableX engineering for
diagnosis.
Start logging early in your app lifecycle — ideally in application:didFinishLaunchingWithOptions:
— so that the log buffer captures the full connection sequence from the moment the SDK
initialises. Once you have reproduced the issue, call postClientLogs on the room
to upload.
Detail
Value
Class
EnxRoom
Method
-(void)postClientLogs
Error Codes
Code
Description
5056
Log upload already in process.
5083
Cannot upload — log file is empty.
// Start logging early in your app lifecycle
let logger = EnxLogger.sharedInstance()
logger?.startLog()
// When you need to report an issue, post logs to EnableX
room.postClientLogs()
// Start logging early in your app lifecycle
EnxLogger *logger = [EnxLogger sharedInstance];
[logger startLog];
// When you need to report an issue, post logs to EnableX
[room postClientLogs];
Tip. Enable logging at app launch during development. Logs capture connection
events, ICE negotiation, and error details that are essential for diagnosing intermittent
issues.