In-Session Communication

Beyond audio and video, the EnableX Web SDK lets participants communicate in a variety of ways within a live session — chat messages, structured custom signals, file transfers, screen and canvas sharing, live streaming to CDNs, whiteboard annotation, and real-time speech transcription.

Messaging

Chat — Text Messaging

EnxRoom.sendMessage() sends a text message to one participant, a group, or everyone in the room. It works even if the sender has not published a stream — useful for observer-mode participants.

ParameterTypeDescription
MessageStringThe text message to send
IsBroadcastBooleantrue = send to everyone; false = send to specified recipients only
RecipientIDsArrayArray of Client IDs. Used when IsBroadcast is false. Pass [] for broadcast.
// Public message — everyone in the room receives it
room.sendMessage("Hello everyone!", true, [], function(data) {
  console.log("Message sent");
});

// Private message — only Alice (clientId) receives it
room.sendMessage("Hey Alice, are you ready?", false, ["alice-client-id"], function(data) {
  console.log("Private message sent");
});

// Receive messages
room.addEventListener("message-received", function(event) {
  var msg = event.message;
  // msg.broadcast    — true if public, false if private/group
  // msg.sender       — sender's name
  // msg.senderId     — sender's client ID
  // msg.message      — the text content
  // msg.timestamp    — Unix timestamp
  // msg.receipients  — array of recipient client IDs (private only)

  if (msg.broadcast) {
    showPublicChatMessage(msg.sender, msg.message);
  } else {
    showPrivateChatMessage(msg.sender, msg.message);
  }
});

Custom Signalling

EnxRoom.sendUserData() is for application-level signalling — sending structured JSON data between participants rather than plain chat text. Use it to synchronize UI state, send poll responses, trigger remote actions, or pass any business-specific payload.

// Example: send a poll response as structured data
var signalData = {
  type:      "poll-response",
  question:  "Q1",
  answer:    "option_b",
  userId:    "alice"
};

// Broadcast to all
room.sendUserData(signalData, true, [], function(data) {
  console.log("Signal sent");
});

// Or send to specific participants
room.sendUserData(signalData, false, ["moderator-client-id"], function(data) {});

// Receive custom signals
room.addEventListener("user-data-received", function(event) {
  var payload = event.message.msg;
  // payload is exactly what the sender put in MessageOpt
  if (payload.type === "poll-response") {
    recordPollAnswer(payload.userId, payload.answer);
  }
});
File Sharing

File sharing lets participants upload files to the EnableX server and share them with others in the session. Files are uploaded once and each recipient downloads independently. Available from Web SDK v1.5.3 onwards.

Upload a File

EnxRoom.sendFiles() uploads one or more files to the EnableX server and notifies intended recipients that a file is available for download.

// fileInput is an <input type="file"> element
var fileList = document.getElementById("fileInput").files;

var shareOptions = {
  isMobile:   false,  // true for WebView-based mobile apps
  broadcast:  true,   // true = share with all; false = share with clientList only
  clientList: []      // Client IDs when broadcast is false
};

room.sendFiles(fileList, shareOptions, function(resp) {
  if (resp.result === 0) {
    console.log("Upload job started, ID:", resp.response.upJobId);
  } else {
    console.error("Upload error:", resp.error);
  }
});

// Track upload progress
room.addEventListener("fs-upload-result", function(event) {
  var msg = event.message;
  switch (msg.messageType) {
    case "upload-started":
      showUploadProgress(msg.response.upJobId, msg.response.uploadInfo.name);
      break;
    case "upload-completed":
      hideUploadProgress(msg.response.upJobId);
      showUploadSuccess(msg.response.uploadInfo.name);
      break;
    case "upload-failed":
      showUploadError(msg.response.upJobId);
      break;
  }
});

Download a Shared File

When a file is shared, recipients are notified via the fs-download-result event with messageType: "download-available". They can then inspect room.availableFiles and initiate a download.

// Listen for new files available for download
room.addEventListener("fs-download-result", function(event) {
  var msg = event.message;

  if (msg.messageType === "download-available") {
    var files = room.availableFiles;
    // files: [{ name: "report.pdf", size: 191002, index: 0 }]
    showDownloadPrompt(files);
  }

  if (msg.messageType === "download-started") {
    showDownloadProgress(msg.response.jobId, msg.response.downloadInfo.name);
  }

  if (msg.messageType === "download-completed") {
    hideDownloadProgress(msg.response.jobId);
  }

  if (msg.messageType === "download-failed") {
    showDownloadError(msg.response.jobId);
  }
});

// Initiate download by file index
function downloadFile(index) {
  room.recvFiles(index, { isMobile: false }, function(resp) {
    if (resp.result !== 0) {
      console.error("Download error:", resp.error);
    }
  });
}

Cancel File Transfers

// Cancel a specific upload (by upJobId)
room.cancelUploads(upJobId, false, function(resp) {
  console.log("Upload cancelled");
});

// Cancel ALL in-progress uploads
room.cancelUploads(null, true, function(resp) {});

// Cancel a specific download (by jobId)
room.cancelDownloads(jobId, false, function(resp) {
  console.log("Download cancelled");
});

// Cancel ALL in-progress downloads
room.cancelDownloads(null, true, function(resp) {});
Screen Share & Canvas Streaming

Screen Sharing

Screen sharing captures the user's screen (or a specific window or tab) and publishes it as a separate stream (Stream ID 101) into the room. To use this feature, the room must be created with "screen_share": true in the room settings.

Room requirement

Screen sharing must be enabled at room creation time: "settings": { "screen_share": true }. Subscribers receive screen share as Stream ID 101.

Start Screen Sharing

var shareOption = {
  audio:  true,          // Capture system audio (if browser supports)
  layout: "presenter"    // Custom hint to receivers for UI layout switching
};

var screenStream = room.startScreenShare(shareOption, function(result) {
  if (result.result !== 0) {
    console.error("Screen share failed:", result.error);
  }
});

// Everyone is notified
room.addEventListener("share-started", function(event) {
  // event.layout — the layout hint sent by the sharer
  if (event.layout === "presenter") switchToPresenterLayout();

  // Subscribe to stream ID 101 to receive the shared screen
  var screenStream = room.remoteStreams.get(101);
  if (screenStream) {
    screenStream.play("screen-share-player", { player: { width: "100%", height: "auto" } });
  }
});

Stop Screen Sharing

room.stopScreenShare(screenStream, function(result) {
  console.log("Screen share stopped");
});

room.addEventListener("share-stopped", function(event) {
  switchToNormalLayout();
});

Force Stop Sharing (Moderator)

A moderator can force-stop any participant's screen share or canvas stream using stopAllSharing(). Available from SDK v2.1.2 onwards.

room.stopAllSharing(function(result) {
  console.log("All sharing stopped by moderator");
});
Error CodeDescription
1143Device not found — screen sharing disabled at OS level
1151Another screen sharing stream is already active in the room

Canvas Streaming

Canvas Streaming publishes an HTML5 <canvas> element as a live video stream (Stream ID 102). Use it to build shared whiteboards, slide presentations, or any dynamic visual — subscribers see your canvas updates in real time. The room must be created with "canvas": true in settings.

Start Canvas Streaming

var canvasOpt = {
  canvasSelector: "myCanvasId",  // The id attribute of the <canvas> element
  fps: 15                         // Frame rate, range: 1–23
};

room.startCanvas(canvasOpt, function(arg) {
  if (arg.result !== 0) {
    console.error("Canvas start failed, code:", arg.result);
  }
});

room.addEventListener("canvas-started", function(event) {
  // Subscribe to stream ID 102 to display the canvas
  var canvasStream = room.remoteStreams.get(102);
  if (canvasStream && canvasStream.stream !== undefined) {
    canvasStream.play("canvas-player");
  }
});
Error CodeDescription
1154Frame rate out of valid range (1–23)
1157Canvas element ID not found in DOM
1158Browser does not support the HTML5 Canvas element
1159Failed to create canvas stream — source canvas ID not in DOM

Stop Canvas Streaming

room.stopCanvas(function(arg) {
  if (arg.result === 0) console.log("Canvas streaming stopped");
});

room.addEventListener("canvas-stopped", function(event) {
  // Remove canvas player from UI
});
Live Streaming

RTMP Live Streaming

Moderators can forward the live session to any RTMP-compatible CDN (YouTube Live, Twitch, Facebook Live, etc.). The session continues normally for participants while simultaneously being broadcast to a wider audience.

Moderator only

Only users with the moderator role can start and stop RTMP streaming.

Start RTMP Forwarding

var streamingConfig = {
  rtmpDetails: {
    rtmpUrl: "rtmp://live.youtube.com/live2/YOUR-STREAM-KEY"
  },
  urlDetails: {
    url: "https://your-custom-streaming-view.example.com/"  // Optional custom view URL
  }
};

room.startStreaming(streamingConfig, function(resp) {
  if (resp.result === 0) {
    console.log("You are now live!");
  } else {
    console.error("Streaming failed:", resp.error);
  }
});

room.addEventListener("streaming-started", function(event) {
  showLiveBadge();
  // event.message.startedBy — who started the stream
});

room.addEventListener("streaming-failed", function(event) {
  hideLiveBadge();
});

Stop RTMP Forwarding

room.stopForwarding(function(resp) {
  console.log("Streaming stopped");
});

room.addEventListener("streaming-stopped", function(event) {
  hideLiveBadge();
  // event.message.stoppedBy — who stopped it
});

HLS Streaming

HLS streaming scales a live video session to very large audiences using adaptive bitrate delivery. Unlike RTMP which targets CDN re-streaming, HLS is EnableX-managed and designed for in-app audience playback.

Subscription required

HLS streaming is a subscription-based service. Contact your EnableX account manager to enable it. If not subscribed, room definitions with HLS settings are rejected.

Room Configuration for HLS

HLS must be enabled in the room definition. The audiences count must be a positive number:

{
  "name": "Webinar Room",
  "settings": {
    "mode": "group",
    "moderators": "1",
    "participants": "4",
    "audiences": 500,
    "hls_view_url": "https://your-domain.com/hls-view/?token=",
    "send_audiences_stats": true,
    "quality": "HD"
  }
}

Audience Token

Audiences join with a special "role": "audience" token. HLS streaming starts automatically when the first audience connects and stops when the last audience leaves.

{
  "name": "Viewer Name",
  "user_ref": "viewer-001",
  "role": "audience"
}

Playing the HLS Stream

When HLS starts, the hls-started event delivers the stream URL. Use the EnableX HLS Player or your own HLS-compatible player.

room.addEventListener("hls-started", function(event) {
  var response = event.message;
  if (!response.error) {
    var hlsUrl = response.hls_url;
    var hlsPlayer = new EnxHls();
    if (hlsPlayer) {
      hlsPlayer.playStreamerURI("hls-player-div", hlsUrl);
    }
  }
});

room.addEventListener("hls-stopped",  function(event) { hideHlsPlayer(); });
room.addEventListener("hls-failed",   function(event) { showHlsError(); });
room.addEventListener("hls-waiting",  function(event) { showHlsWaiting(); });
Presentation Tools

Annotation

Annotation lets participants draw and mark up over a remote stream in real time — useful for tutoring, design reviews, or technical walkthroughs. Annotation uses the canvas streaming infrastructure (Stream ID 102) and therefore requires the room to have "canvas": true in its settings.

Configure the Annotation Toolbar

Before starting annotation, configure the drawing tools available to users.

// Set pen color
room.annotateToolAction("Color", "#ff0000");

// Set line width
room.annotateToolAction("LineWidth", 3);

// Set draw type
room.annotateToolAction("drawType", "Pencil");

// Enable/disable drawing mode
room.annotateToolAction("draw", true);

Start Annotation

// Annotate over a specific remote stream
var targetStream = room.remoteStreams.get(streamId);

room.startAnnotation(targetStream, function(arg) {
  console.log("Annotation started:", arg);
});

room.addEventListener("canvas-started", function(event) {
  if (event.canvasType === "Annotation") {
    // Show annotation overlay UI
    showAnnotationControls();
  }
});

Stop Annotation

room.stopAnnotation(function(arg) {
  console.log("Annotation stopped");
});

room.addEventListener("canvas-stopped", function(event) {
  if (event.canvasType === "Annotation") {
    hideAnnotationControls();
  }
});

Live Transcription

Live transcription converts speech from active talkers into text in real time and delivers it to subscribed endpoints. It is useful for accessibility, multilingual sessions, and meeting notes. Transcription is session-scoped: anyone can start it; it continues until the last subscriber stops.

Subscription required

Live transcription is a subscription-based service. Contact EnableX to enable it for your account. If not subscribed, the method returns error code 3002.

Room Configuration for Transcription

{
  "settings": {
    "live_transcription": {
      "language":       "english_us",
      "auto_transcribe": false,
      "enable":          true
    }
  }
}
SettingDescription
languagePrimary language for the speech engine (e.g., english_us, hindi)
auto_transcribeIf true, transcription starts automatically and does not stop when the last subscriber leaves
enableSet false to disable transcription for this specific room even if your account is subscribed

Start Live Transcription

Use startLiveTranscription() to subscribe yourself to the transcription feed. If you are the first to call it, this also starts the transcription process in the room. Use startLiveTranscriptionForRoom() to start room-level transcription that is shared with all participants.

room.startLiveTranscription("english_us", function(result, error) {
  if (error) console.error("Transcription start failed:", error);
});

// Confirmation events
room.addEventListener("self-transcription-on", function(event) {
  showTranscriptionActiveIndicator();
});

room.addEventListener("room-transcription-on", function(event) {
  showRoomTranscriptionBadge();
});

// Receive transcription text in real time
room.addEventListener("transcription-events", function(event) {
  // event.type: "speech_recognising" (interim) or "speech_recognised" (final)
  // event.text: the transcribed text
  // event.clientID: who is speaking
  // event.duration: speech duration in seconds

  if (event.type === "speech_recognised") {
    appendTranscriptLine(event.clientID, event.text);
  } else {
    // "speech_recognising" — show interim/partial text
    showInterimText(event.text);
  }
});

Stop Live Transcription

room.stopLiveTranscription(function(result, error) {
  console.log("Stopped receiving transcription");
});

room.addEventListener("self-transcription-off", function(event) {
  hideTranscriptionActiveIndicator();
});

room.addEventListener("room-transcription-off", function(event) {
  hideRoomTranscriptionBadge();
});
Error CodeDescription
3002Live transcription subscription not enabled on your account
← Stream Management Session Management →