Stream Management
Stream management covers everything to do with publishing your camera to the room and subscribing to other participants' streams. In the React Native SDK, local stream configuration is declared as part of the <EnxRoom> component's localInfo prop, while all stream actions (publish, mute, switch camera, subscribe) are called imperatively through the Enx API class.
Before publishing your camera and microphone to the room, you need to tell the SDK exactly what media to capture and how your participant should appear to others. This is done through the publishStreamProp object, which you pass as the localInfo prop to <EnxRoom>.
Think of localInfo as your join-time stream declaration. It controls whether audio and video are captured at all, whether you join muted, and what display name other participants see for you. You set this once before connecting — it is not a live toggle, it is the starting state of your local stream.
publishStreamProp Fields
| Field | Type | Default | Description |
|---|---|---|---|
audio |
boolean | true | Capture microphone audio. |
video |
boolean | true | Capture camera video. |
data |
boolean | true | Enable the data channel for in-session messaging. |
name |
string | — | Display name shown to other participants in the room. |
audioMuted |
boolean | false | Join with the microphone muted. Set to true for listen-only entry. |
videoMuted |
boolean | false | Join with the camera off. Set to true for audio-only entry. |
Declare the object in your component and pass it directly to <EnxRoom>:
const localInfo = {
audio: true,
video: true,
data: true,
name: 'Alice',
audioMuted: false,
videoMuted: false
};
// Pass it to EnxRoom
<EnxRoom
localInfo={localInfo}
token={token}
eventHandlers={eventHandlers}
/>
Once the room is connected, you need to explicitly publish your local stream — this is the call that starts sending your camera and microphone feed to other participants. The SDK does not publish automatically on connect; you control exactly when broadcasting begins.
Call Enx.publish() inside your roomConnected handler. The SDK responds asynchronously with a streamPublished callback that carries the local stream's ID. Hold on to that stream ID — it is required for subsequent operations like muting, switching camera, and unsubscribing.
// Call after roomConnected fires
Enx.publish();
Callbacks
| Callback | When it fires |
|---|---|
streamPublished |
Stream published successfully. Payload includes the local stream ID. |
eventError |
Publish attempt failed. Check the error code for the cause. |
streamAdded |
Fired on all participants (including you) when a new stream enters the room. |
In practice, your roomConnected handler triggers the publish, and streamPublished gives you the stream ID to store in component state:
const eventHandlers = {
roomConnected: (data) => {
// Room is ready — start publishing
Enx.publish();
},
streamPublished: (stream) => {
console.log('Published. Local stream ID:', stream.streamId);
this.setState({ localStreamId: stream.streamId });
},
streamAdded: (stream) => {
// A stream (local or remote) appeared in the room
console.log('Stream added:', stream.streamId);
}
};
To display a video stream on screen, use the <EnxPlayerView> JSX component. It handles all native video rendering internally — you only need to provide the stream ID and a style. Use one <EnxPlayerView> instance per stream you want to show: one for your local stream, and one for each remote participant you subscribe to.
import { EnxPlayerView } from 'enx-rtc-react-native';
// Render local stream preview
<EnxPlayerView
streamId={this.state.localStreamId}
style={{ width: '100%', height: 200 }}
/>
// Render a remote stream
<EnxPlayerView
streamId={remoteStreamId}
style={{ width: '100%', height: 200 }}
/>
FlatList or ScrollView to render multiple <EnxPlayerView> components when displaying several participants. Each needs a unique streamId. Keying each list item on streamId ensures React reconciles additions and removals correctly without remounting unrelated views.
Most devices have both a front-facing and a rear-facing camera. Enx.switchCamera(localStreamId) toggles between them mid-session without interrupting the stream. The change takes effect immediately on the device — there is no asynchronous callback to wait for.
Pass the local stream ID that was returned in the streamPublished callback. You must have a published stream before calling this.
// Toggle between front and rear camera
Enx.switchCamera(this.state.localStreamId);
During a session, the user may plug in a headset, connect a Bluetooth device, or simply want to move from the earpiece to the speakerphone. Enx.switchMediaDevice(micDevice) lets you change the active audio output device at any point without ending the call.
Pass one of the following string values as micDevice:
SPEAKER_PHONE— built-in loudspeakerWIRED_HEADSET— plugged-in wired headsetEARPIECE— built-in earpiece (default phone call position)BLUETOOTH— connected Bluetooth headset or earbudsNONE— no specific preference; system default
// Switch to speakerphone
Enx.switchMediaDevice('SPEAKER_PHONE');
// Switch to earpiece
Enx.switchMediaDevice('EARPIECE');
Enx.getDevices() before presenting a device picker. Not all devices expose all audio outputs — for example, BLUETOOTH will only be available if a Bluetooth audio device is currently paired and connected.
Participants frequently need to mute their microphone during a meeting or turn off their camera without leaving the session. The SDK provides dedicated methods for both, operating independently so you can mute audio while keeping video on, or vice versa.
Both methods take the local stream ID and a boolean mute state:
Enx.muteSelfAudio(localStreamId, muteState)— passtrueto mute the microphone,falseto unmute it.Enx.muteSelfVideo(localStreamId, muteState)— passtrueto stop the camera feed,falseto resume it.
These calls affect only your own stream — they do not mute remote participants.
const { localStreamId } = this.state;
// Mute microphone
Enx.muteSelfAudio(localStreamId, true);
// Unmute microphone
Enx.muteSelfAudio(localStreamId, false);
// Stop camera
Enx.muteSelfVideo(localStreamId, true);
// Resume camera
Enx.muteSelfVideo(localStreamId, false);
The SDK exposes a set of optional stream-level behaviours that are off by default. Use Enx.setAdvancedOptions(advanceOptions) to turn them on or off at any point during an active session — not just at join time. Use Enx.getAdvancedOptions(callback) to read whatever settings are currently active.
These options let you opt in to additional event callbacks your handlers can act on, such as receiving video resolution change notifications or battery level updates from participants.
// Enable resolution change events, disable battery updates
Enx.setAdvancedOptions({
notify_video_resolution_change: true,
battery_updates: false
});
// Read the current advanced options
Enx.getAdvancedOptions((options) => {
console.log('Current advanced options:', options);
});
When a remote participant publishes their stream, the SDK fires the streamAdded callback in your event handlers. At this point the stream exists in the room but you are not yet receiving its media — you need to explicitly call Enx.subscribe(remoteStreamID, callback) to start receiving that participant's audio and video.
The subscribe callback delivers a stream object confirming the subscription. Store the stream ID from that object in your state so you can render it via <EnxPlayerView>.
The typical pattern is to subscribe to every stream as it arrives — you handle the decision of what to display in the UI separately, for example by using the active talker list to prioritise which streams appear on screen.
const eventHandlers = {
streamAdded: (stream) => {
// Subscribe to every incoming remote stream as it arrives
Enx.subscribe(stream.streamId, (subscribedStream) => {
console.log('Subscribed to stream:', subscribedStream.streamId);
// Add the stream ID to state so EnxPlayerView can render it
this.setState(prev => ({
remoteStreams: [...prev.remoteStreams, subscribedStream.streamId]
}));
});
}
};
In a multi-participant session you cannot display every participant's video feed simultaneously — both bandwidth and screen real estate are limited. EnableX solves this with active talker management: the server continuously ranks participants by speaking activity and sends your app an ordered list of the most active streams. Your app renders those streams in the primary view, creating a spotlight-style experience that automatically follows the conversation.
The React Native SDK receives up to 6 active talker streams at a time. Whenever the ranking changes — because someone starts speaking, goes quiet, or joins or leaves — the activeTalkerList callback fires with a fresh ordered list.
Receiving the Active Talker List
Wire up the activeTalkerList handler in your eventHandlers object. The payload contains an ActiveTalkers array, ordered from most to least active. Replace your current displayed streams with this list on every callback.
const eventHandlers = {
activeTalkerList: (data) => {
// data.ActiveTalkers is an ordered array of stream objects
const talkers = data.ActiveTalkers;
this.setState({ activeTalkers: talkers });
// Render an EnxPlayerView for each talker using talker.streamId
}
};
Each entry in the ActiveTalkers array has the following structure:
{
streamId: 123, // stream ID to pass to EnxPlayerView
clientId: 'abc', // unique client ID for this participant
name: 'Alice', // participant display name
videoMuted: false, // true if their camera is currently off
audioMuted: false // true if their microphone is currently muted
}
Controlling the Talker Count
You can request a specific number of active talker streams from the server — anywhere from 0 to the platform maximum of 6. Three methods manage this:
Enx.getMaxTalkers(callback)— returns the maximum number of active talker streams the server will send for this platform (6 for React Native).Enx.getTalkerCount(callback)— returns the number of active talker streams currently being requested.Enx.setTalkerCount(numTalkers)— request a specific number of active talker streams. Valid range: 0–6.
// Request 4 active talker streams
Enx.setTalkerCount(4);
// Check the current requested talker count
Enx.getTalkerCount((count) => {
console.log('Current talker count:', count);
});
// Check the platform maximum
Enx.getMaxTalkers((max) => {
console.log('Max talkers:', max); // 6
});
talkerCount to 0 pauses active talker updates entirely. The activeTalkerList callback will stop firing until you call Enx.setTalkerCount(n) again with a value greater than 0. This is useful when the local user is screen sharing or presenting content full-screen and you don't need to track who is speaking.