Developer Tools

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: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.

Detail Value
Class EnxRoom
Method -(void)subscribeForTalkerNotification:(BOOL)enabled

Delegate Methods

Delegate Description
room:didAckSubscribeTalkerNotification: ACK when successfully subscribed.
room:didAckUnsubscribeTalkerNotification: ACK when successfully unsubscribed.
room:didTalkerNotification: Notification with speech and noise data.

Notification Payload

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.
5130 Already subscribed to talker notifications.
5131 Unsubscribing without having subscribed first.
[room subscribeForTalkerNotification:YES];   // Subscribe
[room subscribeForTalkerNotification:NO];    // Unsubscribe

-(void)room:(EnxRoom *)room didAckSubscribeTalkerNotification:(NSArray *)data {
    // Subscribed successfully
}

-(void)room:(EnxRoom *)room didTalkerNotification:(NSArray *)data {
    // data payload example:
    // {
    //   "type": "talker-notification",
    //   "data": [
    //     {
    //       "speech": true,
    //       "users": [
    //         { "speechType": "high",   "clientId": "xxxxx" },
    //         { "speechType": "medium", "clientId": "yyyyy" },
    //         { "speechType": "low",    "clientId": "zzz"   }
    //       ]
    //     },
    //     {
    //       "noise": true,
    //       "users": [
    //         { "clientId": "sssss" },
    //         { "clientId": "uuuuu" }
    //       ]
    //     }
    //   ]
    // }
}
Voice Activity Detection

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: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:.

Test Groups

Group Tests
Microphone Audio capture
Camera Resolution 320×240, 640×480, 1280×720, supported resolutions
Network UDP/TCP/IPv6 via TURN and STUN
Connectivity Relay, reflexive, host connectivity via TURN and STUN
Throughput Data throughput via TURN
Bandwidth Video bandwidth, audio bandwidth via TURN
Signaling Signaling connectivity
Detail Value
Class EnxRtc
Method -(void)clientDiagnostics:(NSDictionary *)Options

Options Parameters

Key Type Description
testNames Array Test group names to run, e.g. ["microphone","camera"] or ["all"].
audioDeviceId String Optional. Audio input device ID to test.
videoDeviceId String Optional. Video input device ID to test.
regionId Array Optional. ICE server regions to test against, e.g. ["IN","US"].
testDurationDataThroughput String Optional. Duration in seconds for the data throughput test (1–30). Default: 2.
testDurationVideoBandwidth String Optional. Duration in seconds for the video bandwidth test (1–30). Default: 10.
testDurationAudioBandwidth String Optional. Duration in seconds for the audio bandwidth test (1–30). Default: 10.
stop Boolean Optional. Set true to stop any currently running tests.

Delegate Methods

Delegate Description
didClientDiagnosisStatus: Fires after each individual test case with an intermediate result JSON object.
didClientDiagnosisFinished: All tests complete — the full diagnostic report JSON is returned.
didClientDiagnosisFailed: Fired when options are invalid or a duplicate call is made while tests are running.
didClientDiagnosisStopped: Fired when tests are explicitly stopped via the stop option.
NSDictionary *options = @{
    @"testNames": @[@"microphone", @"camera", @"network"],
    @"regionId":  @[@"IN"],
    @"testDurationDataThroughput": @"2"
};

[enxRtc clientDiagnostics:options];
[enxRtc setDelegate:self];

// Each test case result
-(void)didClientDiagnosisStatus:(NSArray *)data {
    // {
    //   "test_group": "microphone",
    //   "test_case":  "audio_capture",
    //   "status":     "finished",
    //   "output":     { ... }
    // }
}

// All tests done
-(void)didClientDiagnosisFinished:(NSArray *)data {
    // Full report: grouped by test_group → test_case → result/execution_time/success/error
}

// Stop tests mid-run
NSDictionary *stopOptions = @{@"testNames": @[@"all"], @"stop": @YES};
[enxRtc clientDiagnostics:stopOptions];

-(void)didClientDiagnosisStopped:(NSArray *)data { }
Outbound Calling

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.

Make a Single Outbound Call

Detail Value
Class EnxRoom
Method -(void)makeOutboundCall:(NSString *)number callerId:(NSString *)callerId withDialOptions:(NSDictionary *)dialOptions

Make Multiple Outbound Calls (max 5)

Detail Value
Class EnxRoom
Method -(void)makeOutboundCalls:(NSArray *)numberList callerId:(NSString *)callerId withDialOptions:(NSDictionary *)dialOptions

Parameters

Parameter Type Description
number / numberList String / Array PSTN number or SIP URI to dial.
callerId String 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.

Detail Value
Method -(void)sendDTMF:(NSString *)number digits:(NSString *)digits
Delegate room:didOutBoundCallSendDtmf:
Error Code Description
1155 Invalid parameters.
1201 Invalid dial state — call is not connected.
1202 Dial request not found.
NSDictionary *dialOptions = @{
    @"name":        @"John",
    @"early_media": @NO,
    @"silent_join": @YES
};

// Make a call
[enxRoom makeOutboundCall:@"919999999999"
                 callerId:@"918888888888"
          withDialOptions:dialOptions];

-(void)room:(EnxRoom *)room didOutBoundCallInitiated:(NSArray *)data {
    // Call is dialling
}

-(void)room:(EnxRoom *)room didDialStateEvents:(EnxOutBoundCallState)state {
    // Track: initiated → calling → connecting → connected → terminated
}

// Cancel
[enxRoom cancelOutboundCall:@"919999999999"];

// Send DTMF after call answers
[enxRoom sendDTMF:@"919999999999" digits:@"1"];

-(void)room:(EnxRoom *)room didOutBoundCallSendDtmf:(NSArray *)data {
    // DTMF sent successfully
}
Session Utilities

Audio-Only Mode

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];

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.

Method Description
-(void)stopVideoTracksOnApplicationBackground:(BOOL)flag Stop publishing local video when the app enters the background.
-(void)startVideoTracksOnApplicationForeground:(BOOL)flag Resume publishing local video when the app returns to the foreground.
// 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.
NSDictionary *config = @{
    @"maxVideoBW": @"900",
    @"minVideoBW": @"150",
    @"maxAudioBW": @"150",
    @"minAudioBW": @"150"
};
[stream updateConfiguration:config];

Capture Screenshot

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];

-(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
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.