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.

Local Stream Configuration

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}
/>
Publishing Your Stream

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);
  }
};
Rendering Video — EnxPlayerView

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 }}
/>
Use a 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.
Switching Camera

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);
Switching Audio Output Device

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:

// Switch to speakerphone
Enx.switchMediaDevice('SPEAKER_PHONE');

// Switch to earpiece
Enx.switchMediaDevice('EARPIECE');
Query available devices first with 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.
Muting Your Own Audio and Video

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:

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);
Advanced Stream Options

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);
});
Subscribing to Remote Streams

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]
      }));
    });
  }
};
Active Talker Management

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:

// 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
});
Setting 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.