Developer Tools & Diagnostics

This page covers the diagnostic, monitoring, and utility features available in the EnableX Web SDK. These tools help you test environments before a call starts, monitor media quality in real time during a session, instrument your application with structured logging, and integrate telephony features like PSTN dial-out.

Pre-Call Diagnostics

Before a user joins a session, you can run a pre-call diagnostics test to verify that their microphone, camera, network connection, and media servers are all working as expected. The SDK provides two modes for running this check.

clientDiagnostics()

clientDiagnostics() runs a comprehensive self-test of the client environment. It checks device availability, media access permissions, STUN/TURN reachability, and server connectivity. The test proceeds through multiple stages, emitting events as each stage completes.

Event-Based Mode (Async)

In this mode, you listen for events as each diagnostic stage finishes. This is useful for building a real-time progress UI during the pre-call test.

var options = {
  // Optional: specify which checks to run
};

room.clientDiagnostics(options);

// Listen for stage-by-stage results
room.on("client-diagnosis-status", function(event) {
  console.log("Diagnosis stage:", event);
  // Update progress in UI
});

room.on("client-diagnosis-finished", function(event) {
  console.log("Diagnosis complete:", event);
  // Show final summary
});

room.on("client-diagnosis-failed", function(event) {
  console.error("Diagnosis failed:", event);
});

room.on("client-diagnosis-stopped", function(event) {
  console.log("Diagnosis stopped before completion");
});

Callback Mode (Quick)

Pass a callback as the second argument to get a single result object when the entire test finishes. This is simpler to use when you only need a pass/fail summary.

room.clientDiagnostics(options, function(result) {
  if (result.result === 0) {
    console.log("Pre-call test passed:", result);
  } else {
    console.error("Pre-call test failed:", result.error);
  }
});
EventWhen it Fires
client-diagnosis-statusAfter each individual diagnostic stage completes
client-diagnosis-finishedAll stages have completed successfully
client-diagnosis-failedA critical stage failed and the test cannot continue
client-diagnosis-stoppedThe test was stopped before completing

Client Bitrate Test

The bitrate test measures the upload and download bandwidth available to the client by connecting to an EnableX media server in a specified region. Use this before a session to verify whether the client has sufficient bandwidth for video calls.

var clientInfo = {
  region: "sg"   // Region code: "sg" (Singapore), "in" (India), etc.
};

room.clientBitrate(clientInfo);

room.on("client-bitrate-status", function(event) {
  console.log("Bitrate measurement in progress:", event);
});

room.on("client-bitrate-finished", function(event) {
  console.log("Bitrate test complete:", event);
  // event contains upload/download bandwidth estimates
});
EventWhen it Fires
client-bitrate-statusProgress updates during the bitrate measurement
client-bitrate-finishedTest is complete — payload contains bandwidth estimates
Live Media Stats

subscribeMediaStats()

During an active session, you can subscribe to real-time media statistics for all published streams — including audio/video bitrate, packet loss, jitter, and frame rate. This is useful for building in-session quality indicators or for diagnostics overlays.

subscribeMediaStats(reqType, callback) accepts a reqType string that controls the display and notification behavior:

reqType ValueBehavior
"display"Stats are rendered in the SDK's built-in overlay (if available)
"notify"Stats are delivered via the media-stats event only (no display)
"notify-display"Stats are both displayed and delivered via the event
"disable"Stops stat collection and delivery
// Start receiving stats via event
room.subscribeMediaStats("notify", function(response) {
  if (response.result === 0) {
    console.log("Media stats subscription started");
  }
});

// Handle the stats payload
room.on("media-stats", function(stats) {
  // stats.talkers  — stats for received streams from other participants
  // stats.publisher — stats for your own published stream
  // stats.share    — stats for screen share stream (if active)
  // stats.canvas   — stats for canvas stream (if active)
  console.log("Publisher stats:", stats.publisher);
  console.log("Talker stats:", stats.talkers);
});

The media-stats event payload structure:

{
  "talkers": { /* stats per subscribed stream */ },
  "publisher": { /* stats for the local published stream */ },
  "share": { /* stats for screen share (stream ID 101) */ },
  "canvas": { /* stats for canvas stream (stream ID 102) */ }
}

subscribeForTalkerNotification()

This method subscribes to real-time audio activity notifications. It detects who is speaking and who is making noise, updating your UI accordingly. This is different from the active talker list — it gives you finer-grained speech detection events.

// Enable talker notification
room.subscribeForTalkerNotification(true, function(response) {
  if (response.result === 0) {
    console.log("Talker notifications enabled");
  }
});

// Receive notifications
room.on("talker-notification", function(event) {
  var messages = event.message;
  messages.forEach(function(item) {
    if (item.speech) {
      console.log("Speaking:", item.users.map(u => u.clientId));
    }
    if (item.noise) {
      console.log("Noise detected from:", item.users.map(u => u.clientId));
    }
  });
});

// Disable talker notification
room.subscribeForTalkerNotification(false, function(response) {
  console.log("Talker notifications disabled");
});

The talker-notification event payload structure:

{
  "message": [
    {
      "speech": true,
      "users": [
        { "clientId": "client-abc" }
      ]
    },
    {
      "noise": true,
      "users": [
        { "clientId": "client-xyz" }
      ]
    }
  ]
}
Console Logging

The SDK includes a built-in logger with configurable verbosity. During development, you can set a verbose level to capture detailed WebRTC internals. In production, set a higher level to suppress noise.

setLogLevel()

Set the verbosity of SDK log output using EnxRtc.Logger.setLogLevel(Level). The Level parameter is a number from 0 to 5:

LevelLabelDescription
0DEBUGAll logs including internal WebRTC details
1TRACEDetailed trace logs
2INFOGeneral operational messages
3WARNINGWarnings only
4ERRORErrors only
5NONEAll logging suppressed
// In development: capture all logs
EnxRtc.Logger.setLogLevel(0);

// In production: errors only
EnxRtc.Logger.setLogLevel(4);

setOutputFunction()

By default, SDK logs go to the browser console. You can redirect them to a custom function — for example to send logs to your own analytics backend or to filter by component.

EnxRtc.Logger.setOutputFunction(function(level, message) {
  // level: number (0-5)
  // message: string log line
  myLogService.send({ level: level, log: message });
});

postClientLogs()

This method sends the last 500 log lines from the SDK's internal buffer directly to EnableX's log servers. Use this when a user reports an issue — it gives EnableX support teams the raw SDK logs for debugging without requiring users to copy from the browser console.

EnxRtc.postClientLogs(Token, function(response) {
  if (response.result === 0) {
    console.log("Logs submitted to EnableX");
  } else {
    console.error("Log submission failed:", response.error);
  }
});
Tip: Call postClientLogs() in your application's error boundary or user feedback flow so that support logs are captured automatically when users report problems.
Utility Features

Video Frame Snapshot

getVideoFrameImage() captures a still image from a stream's video track and renders it to an HTML Canvas element. This is useful for building profile picture capture, visual debugging overlays, or attendance verification workflows.

// stream can be a local or remote EnxStream
stream.getVideoFrameImage();

// The frame is drawn to the canvas element associated with the stream's player.
// Access it via the DOM after calling this method.

Audio-Only Mode

setAudioOnlyMode(AudioOnly) switches the session between full audio+video mode and audio-only mode. When audio-only mode is enabled, all video tracks are suspended — which reduces bandwidth usage significantly. This is helpful when users are on poor network connections.

// Switch to audio-only (drops all video streams)
room.setAudioOnlyMode(true);

// Restore video
room.setAudioOnlyMode(false);
Note: Switching to audio-only mode affects all incoming video streams, not just your own. The local stream's video is also suspended. Use this as a bandwidth-saving measure for degraded network conditions.
PSTN / SIP Dial-Out

The EnableX Web SDK supports outbound telephony calls directly from within a video session. This allows you to invite PSTN (phone) or SIP participants who do not have an internet connection or the EnableX app. The call is established as part of the video room — the phone participant joins as an audio-only participant.

makeOutboundCall()

Initiate an outbound call to a phone number from within the session. The call state is tracked through a series of events.

var options = {
  name: "John Doe",         // Display name for the called participant
  early_media: true,        // Play ringback tone to the room while waiting
  silent_join: false        // If true, the dialed participant joins silently
};

room.makeOutboundCall(
  dialout_number,           // E.164 phone number, e.g. "+6512345678"
  cli_number,               // Caller Line ID (your outbound number)
  options,
  function(response) {
    if (response.result === 0) {
      console.log("Outbound call initiated");
    } else {
      console.error("Call failed:", response.error);
    }
  }
);

Track the call lifecycle by listening to the dial-state-events event:

room.on("dial-state-events", function(event) {
  switch (event.state) {
    case "initiated":
      console.log("Call initiated to:", event.number);
      break;
    case "dialing":
      console.log("Ringing...");
      break;
    case "connected":
      console.log("Call connected — participant joined as audio-only");
      break;
    case "dtmf-collected":
      console.log("DTMF digits collected:", event.digits);
      break;
    case "disconnected":
      console.log("Call ended:", event.cause);
      break;
  }
});
State ValueMeaning
initiatedThe dial-out request has been sent to the network
dialingThe remote phone is ringing
connectedThe participant answered and is now in the session
dtmf-collectedThe remote participant entered DTMF digits (IVR response)
disconnectedThe call has ended (by either party)

sendDTMF()

Send DTMF tones to a connected call participant. This is used when the called party is behind an IVR menu and needs to press keys to navigate (e.g. "Press 1 to confirm the meeting").

var options = {
  number: "+6512345678",    // The number to send DTMF to
  digits: "1234"            // The DTMF tone sequence to send
};

room.sendDTMF(options, function(response) {
  if (response.result === 0) {
    console.log("DTMF sent successfully");
  } else {
    console.error("DTMF failed:", response.error);
  }
});
Error CodeMeaning
1155No active outbound call to send DTMF to
1201Invalid phone number format
1202Invalid DTMF digits — use only 0–9, *, #