Stream Management

Stream management is the heart of any EnableX video session. There are two kinds of streams you work with: a local stream — the audio and video your device captures and publishes to the room — and remote streams — the audio and video sent by other participants that you subscribe to and render on screen. This page walks through the full lifecycle of both: creating and publishing your own stream, subscribing to others, controlling media (mute, camera switching), managing active talkers, and tuning receive quality.

Create a Local Stream

Before you can publish anything to the room, you need a local stream — an EnxStream object that captures audio and/or video from the device's microphone and camera. You create this by calling getLocalStream() on your EnxRoom instance and passing a dictionary that describes which tracks to include and how the stream should behave at join time.

The typical place to call this is inside your room:didConnect: delegate, immediately after the connection is confirmed and before you call publish(). The SDK validates the options, requests any required device permissions, and returns the stream object — which you then pass to publish().

Detail Value
Class EnxRoom
Method -(EnxStream *)getlocalStream:(NSDictionary *)publishStreamInfo
Returns EnxStream — the local stream object, ready to publish

publishStreamInfo Options

The publishStreamInfo dictionary controls which media tracks are included and the initial mute state. You can also attach custom metadata to the stream using the attributes object — this metadata is visible to all other participants.

Key Type Description
audio Boolean Include the microphone audio track.
video Boolean Include the camera video track.
data Boolean Include a data channel for in-stream messaging.
audioMuted Boolean Join the room with audio muted from the start.
videoMuted Boolean Join the room with video muted from the start.
attributes NSDictionary Custom key-value metadata attached to the stream (visible to all participants).
- (void)room:(EnxRoom *)room didConnect:(NSDictionary *)roomMetadata {
    NSDictionary *streamInfo = @{
        @"audio"      : @YES,
        @"video"      : @YES,
        @"data"       : @YES,
        @"audioMuted" : @NO,
        @"videoMuted" : @NO,
        @"attributes" : @{
            @"custom1": @"value"
        }
    };

    EnxStream *localStream = [room getlocalStream:streamInfo];
    [room publish:localStream];
}

Error Codes

Code Meaning
5015 No media tracks — both audio and video are set to false.
5016 Invalid or malformed attributes object.
5017 Camera and microphone access denied by the user.
5018 Camera access failed; stream will be audio-only.
5019 Microphone access denied.
5084 Invalid video layer specified — maximum allowed is 3.
5088 Invalid frame rate — maximum allowed is 30 fps.
Publish a Local Stream

Once you have a local stream, you publish it to the room so that other participants can see and hear you. Calling publish() sends the stream to the EnableX media server, which then distributes it to all connected subscribers. Until you publish, your audio and video exist only on your device — no one else in the room receives them.

Publishing generates two delegate callbacks: one delivered privately to you as an acknowledgement, and one broadcast to everyone in the room (including yourself) announcing that a new stream is available.

Detail Value
Class EnxRoom
Method -(void)publish:(EnxStream *)stream

Delegate Methods

// Publish the local stream after room connects
- (void)room:(EnxRoom *)room didConnect:(NSDictionary *)roomMetadata {
    NSDictionary *streamInfo = @{
        @"audio": @YES,
        @"video": @YES,
        @"data" : @YES
    };
    EnxStream *localStream = [room getlocalStream:streamInfo];
    [room publish:localStream];
}

// ACK — only you receive this; attach your local preview here
- (void)room:(EnxRoom *)room didPublishStream:(EnxStream *)stream {
    EnxPlayerView *playerView = [[EnxPlayerView alloc] initWithFrame:self.localView.bounds];
    [stream attachRenderer:playerView];
    [self.localView addSubview:playerView];
}

// Broadcast — all participants receive this for every stream
- (void)room:(EnxRoom *)room didAddedStream:(EnxStream *)stream {
    // If this is not your own stream, subscribe to it
    if (![stream.streamId isEqualToString:room.localStream.streamId]) {
        [room subscribe:stream];
    }
}

Error Codes

Code Meaning
5013 Room is not connected.
5015 Stream has no media tracks.
5016 Invalid stream attributes.
5022 No floor access — participant cannot publish in lecture mode without moderator grant.
5023 Stream is already published.
5024 Publish is already in progress.
5025 Cannot call publish on a remote stream.
1170 General publish failure.
Unpublish a Local Stream

Unpublishing removes your stream from the room without disconnecting you from the session. Other participants stop receiving your audio and video, and the room notifies everyone that the stream has been removed. You remain connected and can publish again later if needed.

Call unpublish on the EnxStream object (not on the room). The room instance does not need to be referenced directly for this operation.

Detail Value
Class EnxStream
Method -(void)unpublish
Delegate room:didRemovedStream: — broadcast to all participants
// Stop publishing your local stream
[localStream unpublish];

// All participants (including you) receive this when any stream is removed
- (void)room:(EnxRoom *)room didRemovedStream:(EnxStream *)stream {
    // Remove the corresponding player view from your UI
    NSLog(@"Stream removed: %@", stream.streamId);
}

Error Codes

Code Meaning
5029 Unpublish already in progress.
5030 Stream has not been published yet.
Switch Camera, Microphone, and Speaker

During a live session you may need to change which camera is active, switch to a different microphone input, or change audio output routing. The SDK provides dedicated methods on both EnxStream and EnxRoom for each of these operations.

Switch Camera Preview

Use switchCameraPreview to toggle the camera view between front-facing and rear-facing without interrupting the published stream. This is useful when you want the user to preview the rear camera before switching the live feed.

Detail Value
Class EnxStream
Method -(void)switchCameraPreview
// Switch the local camera preview (does not affect published stream)
[localStream switchCameraPreview];

Switch Front / Rear Camera

switchCamera flips the active camera between front-facing and rear-facing and immediately updates the published stream. All subscribers in the room see the new camera angle without re-subscribing.

Detail Value
Class EnxStream
Method -(NSException *)switchCamera
NSException *exception = [localStream switchCamera];
if (exception) {
    NSLog(@"Camera switch failed: %@", exception.reason);
}
Error Code Meaning
5021 Cannot switch camera — session is in audio-only mode.
5097 Cannot switch camera — room is in chat-only mode.

Switch Microphone / Audio Output

Use switchMediaDevice on the room to route audio through a different input or output device — for example switching from the speakerphone to a connected Bluetooth headset, or from the earpiece to the speaker. Pass the device name string as returned by getDevices.

Detail Value
Class EnxRoom
Method -(void)switchMediaDevice:(NSString *)mediaName
Delegate didNotifyDeviceUpdate:(NSString *)updates — fires with the new device name
// Switch audio output to the speakerphone
[room switchMediaDevice:@"Speaker"];

// Delegate fires after the switch completes
- (void)didNotifyDeviceUpdate:(NSString *)updates {
    NSLog(@"Audio device changed to: %@", updates);
    // Refresh your device selection UI to highlight the new active device
}
Mute and Unmute Self

Participants can mute their own audio or video at any time without unpublishing their stream. When you mute yourself, the track is silenced or blacked out on all subscribers' screens. Unmuting restores the track. The SDK fires delegate events both to you (as an acknowledgement) and to the rest of the room (as a notification), so every participant's UI can reflect the change.

Mute / Unmute Audio

Call muteSelfAudio: with YES to mute or NO to unmute your microphone. Pass the boolean based on the desired end-state, not a toggle.

Detail Value
Class EnxStream
Method -(void)muteSelfAudio:(BOOL)isMuted

Delegate methods:

// Mute your microphone
[localStream muteSelfAudio:YES];

// Unmute your microphone
[localStream muteSelfAudio:NO];

// ACK for the local user
- (void)didAudioEvent:(NSDictionary *)data {
    NSLog(@"Audio mute state changed: %@", data);
}

// Room-wide notifications
- (void)stream:(EnxStream *)stream didRemoteStreamAudioMute:(NSArray *)data {
    // Update the mute indicator for this participant in your UI
}

- (void)stream:(EnxStream *)stream didRemoteStreamAudioUnMute:(NSArray *)data {
    // Remove the mute indicator for this participant in your UI
}
Error codes 5058–5062 cover invalid states for audio mute operations (e.g. attempting to mute when already muted, or when the stream has no audio track).

Mute / Unmute Video

muteSelfVideo: follows the same pattern as audio muting. Subscribers see a blacked-out frame while video is muted. The stream remains subscribed and active; only the video track is suppressed.

Detail Value
Class EnxStream
Method -(void)muteSelfVideo:(BOOL)isMuted

Delegate methods:

// Mute your camera video
[localStream muteSelfVideo:YES];

// Unmute your camera video
[localStream muteSelfVideo:NO];

- (void)didVideoEvent:(NSDictionary *)data {
    NSLog(@"Video mute state changed: %@", data);
}

- (void)stream:(EnxStream *)stream didRemoteStreamVideoMute:(NSArray *)data {
    // Show a camera-off placeholder in the participant tile
}

- (void)stream:(EnxStream *)stream didRemoteStreamVideoUnMute:(NSArray *)data {
    // Restore the video frame in the participant tile
}
Subscribe to a Remote Stream

When a participant publishes a stream, the room notifies all connected clients via room:didAddedStream:. At this point the stream exists on the server, but you are not yet receiving media for it. To start receiving audio and video from that participant, you must explicitly call subscribe() on the stream object. This is a deliberate design — it lets you choose which streams to receive, which is important for bandwidth management in larger rooms.

After subscribing, the SDK fires room:didSubscribeStream: with the fully initialised stream. This is where you create an EnxPlayerView, attach the stream to it, and add it to your view hierarchy.

You must call subscribe() individually for each remote stream. There is no "subscribe all" shortcut. Screen share streams arrive with StreamID 101 and canvas streams with StreamID 102 — handle these separately if your app supports them.
Detail Value
Class EnxRoom
Method -(void)subscribe:(EnxStream *)stream
Delegate room:didSubscribeStream: — fires when subscription is confirmed
// Subscribe when the room notifies you of a new stream
- (void)room:(EnxRoom *)room didAddedStream:(EnxStream *)stream {
    [room subscribe:stream];
}

// Once subscribed, attach a player view and render the stream
- (void)room:(EnxRoom *)room didSubscribeStream:(EnxStream *)stream {
    CGRect frame = CGRectMake(0, 0, 160, 120);
    EnxPlayerView *playerView = [[EnxPlayerView alloc] initWithFrame:frame];
    [stream attachRenderer:playerView];
    [self.view addSubview:playerView];
}

Error Codes

Code Meaning
5014 Room is not in a connected state.
5026 Already subscribed to this stream.
5027 Subscription is already in progress.
5028 Cannot call subscribe on a local stream.
Active Talker Management

In a room with many participants, it is not practical (or efficient) to render every stream simultaneously. EnableX addresses this with the Active Talker List — the SDK continuously monitors audio levels and maintains a ranked list of up to 12 participants who are currently speaking. Your app receives updates to this list automatically and should refresh its layout in response.

The way you receive and display active talkers depends on the activeviews setting you passed when connecting:

Active Talker Delegates

// activeviews: "list" — you manage the layout
- (void)room:(EnxRoom *)room didActiveTalkerList:(NSArray *)streams {
    // Clear current video tiles and rebuild from the updated stream list
    [self rebuildVideoGrid:streams];
}

// activeviews: "view" — add the SDK-managed view once
- (void)room:(EnxRoom *)room didActiveTalkerView:(UIView *)view {
    view.frame = self.videoContainerView.bounds;
    [self.videoContainerView addSubview:view];
}

// Available participant count changed
- (void)room:(EnxRoom *)room didAvailable:(NSDictionary *)data {
    NSLog(@"Participants available: %@", data);
}

Get Maximum Talker Count

getMaxTalkers queries the server for the maximum number of active video streams the room configuration allows. This is a room-level setting and does not change during a session. Use this value to cap your UI layout or inform the user of the room's maximum concurrent video feeds.

Detail Value
Class EnxRoom
Method -(void)getMaxTalkers
Delegate room:didGetMaxTalkers:(NSDictionary *)data
[room getMaxTalkers];

- (void)room:(EnxRoom *)room didGetMaxTalkers:(NSDictionary *)data {
    // data = { "result": 0, "maxTalkers": 4 }
    NSInteger maxTalkers = [data[@"maxTalkers"] integerValue];
    NSLog(@"Room max talkers: %ld", (long)maxTalkers);
}

Get Current Talker Count

getTalkerCount queries how many active talker slots are currently configured for your session. This is the number you (or the room settings) have chosen to display, which may be less than the room maximum.

Detail Value
Class EnxRoom
Method -(void)getTalkerCount
Delegate room:didGetTalkerCount:(NSDictionary *)data
[room getTalkerCount];

- (void)room:(EnxRoom *)room didGetTalkerCount:(NSDictionary *)data {
    // data = { "result": 0, "numTalkers": 4 }
    NSInteger numTalkers = [data[@"numTalkers"] integerValue];
    NSLog(@"Current talker count: %ld", (long)numTalkers);
}

Set Talker Count

Use setTalkerCount: to change how many simultaneous video streams the active talker list includes. The value can be between 0 and 12. Setting it to 0 is a special case — it means the SDK will maintain 3 audio-only streams instead of video.

This is particularly useful in response to bandwidth alerts: when available bandwidth drops, you can reduce the talker count to lower the total video bitrate in the room.

Detail Value
Class EnxRoom
Method -(void)setTalkerCount:(NSInteger)numTalkers
Valid Range 0–12 (0 = 3 audio-only streams)
Delegate room:didSetTalkerCount:(NSDictionary *)data
Error 5055 — invalid talker count value
// Reduce active video streams to 4 (e.g. in response to a bandwidth alert)
[room setTalkerCount:4];

- (void)room:(EnxRoom *)room didSetTalkerCount:(NSDictionary *)data {
    NSLog(@"Talker count updated: %@", data);
}
Player View Utilities

When activeviews: "view" is active, the SDK manages the video grid layout internally. These utilities let you interact with that managed layout — highlight specific participants, change background colours, force a refresh, or switch between layout modes. All methods in this section are available from iOS SDK 2.1.3 unless noted otherwise.

These utilities only apply when activeviews: "view" is set during connect(). They have no effect in list mode, where you control the layout yourself.

getPlayer

Retrieve the EnxPlayerView for a specific participant by their clientID. Use this when you need to apply custom styling or overlay to a single participant's tile without affecting others.

Detail Value
Class EnxRoom
Method -(EnxPlayerView *)getPlayer:(NSString *)clientID
Returns EnxPlayerView for the given client, or nil if not found
EnxPlayerView *playerView = [room getPlayer:@"CLIENT_ID"];
if (playerView) {
    // Apply custom styling, border, or overlay to this participant's tile
}

highlightBorderForClient

Highlight the border of one or more participant tiles — useful for indicating who is speaking, who has raised their hand, or who has been selected as the spotlight speaker. Pass an array of client ID strings.

Detail Value
Class EnxRoom
Method -(void)highlightBorderForClient:(NSArray *)clientIDs
// Highlight the speaking indicator for specific participants
[room highlightBorderForClient:@[@"CLIENT_ID_1", @"CLIENT_ID_2"]];

changeBgColorForClients

Change the background colour of specific participant tiles — for example to visually distinguish the moderator, indicate a raised hand, or apply role-based colour coding.

Detail Value
Class EnxRoom
Method -(void)changeBgColorForClients:(NSArray *)clientIDs withColor:(UIColor *)color
// Highlight the moderator's tile with a distinct background colour
[room changeBgColorForClients:@[@"MODERATOR_CLIENT_ID"]
                    withColor:[UIColor colorWithRed:0.2 green:0.6 blue:1.0 alpha:0.4]];

forceUpdateATList

Force the SDK to reload and re-render the active talker view immediately. Call this after making programmatic changes to the layout or after returning from a different view controller to ensure the grid is up to date.

Detail Value
Class EnxRoom
Method -(void)forceUpdateATList
// Force a refresh of the active talker grid
[room forceUpdateATList];

switchATView

Switch the active talker grid between two layout modes: "leader" — which shows one prominent speaker tile with smaller tiles for others — and "gallery" — which shows all active participants at equal size. Available from iOS SDK 2.1.2.

Detail Value
Class EnxRoom
Method -(void)switchATView:(NSString *)viewString
Valid Values "leader" or "gallery"
// Switch to leader layout (one prominent + smaller tiles)
[room switchATView:@"leader"];

// Switch to gallery layout (equal-size tiles)
[room switchATView:@"gallery"];
Receive Video Quality

By default, EnableX automatically selects the best video quality for incoming streams based on available bandwidth. However, you can override this and pin the receive quality to a specific level — useful when you know the device or network conditions warrant a fixed setting, or when building a user-facing quality selector in your settings UI.

Call setReceiveVideoQuality: on the room object with one of the four quality levels. The change applies to all incoming remote streams. The SDK confirms the change via delegate.

Detail Value
Class EnxRoom
Method -(void)setReceiveVideoQuality:(NSString *)videoQuality
Delegate room:didSetVideoQuality:(NSDictionary *)data
Error 5057 — the requested quality level is already active

Quality Levels

Value Description
Auto SDK selects quality automatically based on bandwidth conditions (default).
HD High-definition video. Requires strong network conditions.
SD Standard-definition video. Balanced quality and bandwidth use.
LD Low-definition video. Minimal bandwidth consumption.
// Pin incoming video quality to standard-definition
[room setReceiveVideoQuality:@"SD"];

- (void)room:(EnxRoom *)room didSetVideoQuality:(NSDictionary *)data {
    NSLog(@"Receive video quality updated: %@", data);
}
Set the receive quality to LD when responding to a bandwidth alert (room:didRoomBandwidthAlert:), and restore it to Auto once bandwidth recovers. This keeps call quality as high as conditions allow without manually tracking thresholds.