In-Session Communication

Beyond audio and video, EnableX sessions support a rich set of data communication features: text chat, file sharing, custom signaling, annotation on remote streams, screen sharing, and canvas streaming. None of these features require a published media stream to work — a chat-only participant can send and receive messages without a camera or microphone.

Chat Messaging

sendMessage() sends a text message to one participant, a group, or everyone in the room. The sender does not need to have a published stream for messaging to work.

EventFired ToDescription
onAcknowledgedSendDataSenderConfirms the message was delivered successfully
onMessageReceivedRecipientsDelivers the incoming message to each recipient
// Public broadcast to everyone
window.EnxRtc.sendMessage("Hello everyone!", true, []);

// Private message to a specific participant
window.EnxRtc.sendMessage("Hi there", false, ["client_id_123"]);

// Sender acknowledgement
window.EnxRtc.addEventListner("onAcknowledgedSendData", function(data) {
    console.log("Message delivered:", JSON.stringify(data.data));
});

// Incoming message at receiver's end
window.EnxRtc.addEventListner("onMessageReceived", function(data) {
    var msg = data.data;
    console.log("New message from:", msg.senderId, "—", msg.message);
    appendMessageToChat(msg);
});
File Sharing

Session participants can share files with each other using a two-step process: the sender uploads the file to the EnableX server, and recipients are notified when the file is ready to download.

Upload a File for Sharing

sendFiles() initiates a file transfer to the EnableX server. You can broadcast the file to all participants or target specific recipients by their client IDs.

EventFired ToDescription
onInitFileUploadSenderUpload process has started
onFileUploadedSenderFile has been uploaded successfully
onFileUploadFailedSenderUpload failed (see error codes below)
onFileUploadStartedRecipientsA file upload has started and is incoming
onFileAvailableRecipientsFile is ready to download
// Send to everyone
window.EnxRtc.sendFiles(true, []);

// --- Sender event listeners ---
window.EnxRtc.addEventListner("onInitFileUpload", function(data) {
    console.log("Upload started:", JSON.stringify(data.data));
});

window.EnxRtc.addEventListner("onFileUploaded", function(data) {
    console.log("File uploaded successfully:", JSON.stringify(data.data));
});

window.EnxRtc.addEventListner("onFileUploadFailed", function(data) {
    console.error("Upload failed:", JSON.stringify(data.data));
});

// --- Receiver event listeners ---
window.EnxRtc.addEventListner("onFileUploadStarted", function(data) {
    console.log("Incoming file upload:", JSON.stringify(data.data));
});

window.EnxRtc.addEventListner("onFileAvailable", function(data) {
    console.log("File ready to download:", JSON.stringify(data.data));
    showDownloadPrompt(data.data);
});
Error CodeDescription
5089Storage access denied
5091File sharing is not available in this context
1185File is too large; maximum allowed size exceeded
1182Failed to upload the file

Cancel a File Upload

Cancel a specific in-progress upload by its job ID, or cancel all active uploads at once.

// Cancel a single upload
window.EnxRtc.cancelUpload(jobId);

// Cancel all uploads
window.EnxRtc.cancelAllUploads();

// Event fired when an upload is cancelled
window.EnxRtc.addEventListner("onFileUploadCancelled", function(data) {
    console.log("Upload cancelled:", JSON.stringify(data.data));
});

Download a Shared File

When onFileAvailable fires, the recipient knows a file is ready. Call getAvailableFiles() to retrieve the full list of downloadable files, then call downloadFile() to download a specific one.

// Step 1: Get all files available for download
window.EnxRtc.getAvailableFiles(
    function(data) {
        console.log("Available files:", JSON.stringify(data.data));
        // data.data is an array of file info objects
    },
    function(err) { console.error("Error:", JSON.stringify(err)); }
);

// Step 2: Download a specific file
// fileInfo comes from onFileAvailable or getAvailableFiles
// isAutoSave: true = SDK saves file and returns path
//             false = SDK returns raw Base64 data for manual saving
window.EnxRtc.downloadFile(fileInfo, true);

window.EnxRtc.addEventListner("onInitFileDownload", function(data) {
    console.log("Download started:", JSON.stringify(data.data));
});

window.EnxRtc.addEventListner("onFileDownloaded", function(data) {
    // data.data contains the file path (if autoSave=true) or Base64 data
    console.log("Downloaded:", JSON.stringify(data.data));
});

window.EnxRtc.addEventListner("onFileDownloadFailed", function(data) {
    console.error("Download failed:", JSON.stringify(data.data));
});

Cancel a File Download

// Cancel a single download
window.EnxRtc.cancelDownload(jobId);

// Cancel all active downloads
window.EnxRtc.cancelAllDownloads();

window.EnxRtc.addEventListner("onFileDownloadCancelled", function(data) {
    console.log("Download cancelled:", JSON.stringify(data.data));
});
Error CodeDescription
5089Storage access denied
5090Failed to save file
1183Failed to download file
1181File download not available in this context
Custom Signaling

sendUserData() lets you pass arbitrary structured data to one or more participants. The EnableX server does not enforce any schema on the payload — you define the keys to match your application's needs. Use this to build features like polling, raise-hand mechanisms, or any custom workflow that requires passing data between participants.

EventFired ToDescription
onAcknowledgedSendDataSenderData was sent successfully
onUserDataReceivedRecipientsCustom data received from another participant
// Custom payload — define any structure you need
var message = {
    sender: "John",
    message: "Voting for you",
    candidate: 5,
    rating: 3
};

// Broadcast to everyone
window.EnxRtc.sendUserData(message, true, []);

// Or send to specific participants
window.EnxRtc.sendUserData(message, false, ["client_id_1", "client_id_2"]);

// Sender confirmation
window.EnxRtc.addEventListner("onAcknowledgedSendData", function(data) {
    console.log("Data sent:", JSON.stringify(data.data));
});

// Receiving end
window.EnxRtc.addEventListner("onUserDataReceived", function(data) {
    console.log("Custom data received:", JSON.stringify(data.data));
    handleCustomSignal(data.data);
});
Annotation

Annotation lets one participant draw and mark up another participant's video stream in real time. The annotator starts annotation on a target client's stream, and all participants in the room are notified.

Start Annotation

EventFired ToDescription
onStartAnnotationAckAnnotatorConfirms annotation has started
onAnnotationStartedAll participantsNotifies everyone that annotation is active
window.EnxRtc.startAnnotation(clientId);

window.EnxRtc.addEventListner("onStartAnnotationAck", function(data) {
    console.log("Annotation started (ack):", JSON.stringify(data.data));
    showAnnotationToolbar();
});

window.EnxRtc.addEventListner("onAnnotationStarted", function(data) {
    console.log("Annotation active (all):", JSON.stringify(data.data));
    showAnnotationIndicator();
});

Stop Annotation

EventFired ToDescription
onStoppedAnnotationAckAnnotatorConfirms annotation has stopped
onAnnotationStoppedAll participantsNotifies everyone that annotation ended
window.EnxRtc.stopAnnotation();

window.EnxRtc.addEventListner("onStoppedAnnotationAck", function(data) {
    console.log("Annotation stopped (ack):", JSON.stringify(data.data));
    hideAnnotationToolbar();
});

window.EnxRtc.addEventListner("onAnnotationStopped", function(data) {
    console.log("Annotation ended (all):", JSON.stringify(data.data));
    hideAnnotationIndicator();
});
Screen Sharing

Screen sharing publishes the device's screen as a video stream into the room at 6 fps. It carries on Stream ID 101 — other participants must subscribe to stream ID 101 to receive and display it.

To support screen sharing, the room must be created with settings.screen_share: true in the Room Creation API payload.

Start Screen Sharing

var viewOptions = {
    height: 130,
    width: 100,
    margin_top: 50,
    margin_left: 0,
    margin_right: 15,
    margin_bottom: 10,
    position: "top"
};

window.EnxRtc.addScreenShare(
    viewOptions,
    function(data) { console.log("Screen share started:", JSON.stringify(data.data)); },
    function(err)  { console.error("Error:", JSON.stringify(err)); }
);

// All participants (including presenter) receive this
window.EnxRtc.addEventListner("onScreenSharedStarted", function(data) {
    console.log("Screen share active:", JSON.stringify(data.data));
    // Subscribe to stream ID 101 to view the shared screen
    subscribeToStream("101");
});

Stop Screen Sharing

Screen sharing continues even when the app is in the background. Call removeScreenShare() explicitly to stop it.
window.EnxRtc.removeScreenShare(
    function(data) { console.log("Screen share stopped:", JSON.stringify(data.data)); },
    function(err)  { console.error("Error:", JSON.stringify(err)); }
);

window.EnxRtc.addEventListner("onScreenSharedStopped", function(data) {
    console.log("Screen share ended:", JSON.stringify(data.data));
    removeScreenShare(); // Clean up the view
});
Canvas Streaming

Canvas Streaming publishes any UI view into the room as a video stream. It is carried on Stream ID 102 — participants must subscribe to stream ID 102 to receive the canvas content.

Canvas streaming must be enabled at room creation: set settings.canvas: true in the Room Creation API payload.

Start Canvas Streaming

var options = {
    height: 130,
    width: 100,
    margin_top: 50,
    margin_left: 0,
    margin_right: 15,
    margin_bottom: 10,
    position: "top"
};

window.EnxRtc.addCanvasScreen(
    options,
    function(data) { console.log("Canvas streaming started:", JSON.stringify(data.data)); },
    function(err)  { console.error("Error:", JSON.stringify(err)); }
);

window.EnxRtc.addEventListner("onCanvasStarted", function(data) {
    console.log("Canvas active:", JSON.stringify(data.data));
    // Subscribe to stream ID 102 to view the canvas
    subscribeToStream("102");
});

Stop Canvas Streaming

window.EnxRtc.removeCanvasScreen(
    function(data) { console.log("Canvas stopped:", JSON.stringify(data.data)); },
    function(err)  { console.error("Error:", JSON.stringify(err)); }
);

window.EnxRtc.addEventListner("onCanvasStopped", function(data) {
    console.log("Canvas ended:", JSON.stringify(data.data));
    removeCanvasScreen(); // Clean up the view
});