Session Management
Moderators have a rich set of controls to manage the lifecycle and behaviour of a live video session — from recording and muting to dropping users, locking the room, and concluding the conference.
Legacy Recording
Legacy recording captures each participant's stream individually as MKV files. Post-session, EnableX can transcode these into a single composite MP4 via a subscription-based service. Recording can be started and stopped multiple times in a session with no limit on the number of segments.
Configure "auto_recording": true in room settings to start recording automatically when the session begins. The moderator can still stop and restart recording manually.
Start Recording
- Method:
EnxRoom.startRecord(Callback) - Event:
room-record-on— broadcast to all when recording starts (includes moderator ID)
room.startRecord(function(result, error) {
if (result === 0) {
console.log("Recording started");
}
});
room.addEventListener("room-record-on", function(event) {
showRecordingIndicator();
// event.message.moderatorId — who started recording
});
Stop Recording
- Method:
EnxRoom.stopRecord(Callback) - Event:
room-record-off— broadcast to all when recording stops
room.stopRecord(function(result, error) {
if (result === 0) {
console.log("Recording stopped");
}
});
room.addEventListener("room-record-off", function(event) {
hideRecordingIndicator();
});
Live Recording
Live recording (SDK v2.1.2+) creates a transcoded MP4 file in real time during the session using a custom layout. Unlike legacy recording, the output file is available within minutes of the session ending — no long transcoding queue. You link a custom web view that acts as the recording layout.
Start Live Recording
- Method:
EnxRoom.startLiveRecording(config, Callback) - Events:
room-live-recording-on,room-live-recording-failed,room-live-recording-updated
var recordConfig = {
urlDetails: {
url: "https://your-custom-layout.example.com/",
chatOverlay: false,
layOut: {} // Any custom layout options your view handles
}
};
room.startLiveRecording(recordConfig, function(resp) {
if (resp.data.status.resultCode === 0) {
console.log("Live recording initiated");
}
});
room.addEventListener("room-live-recording-on", function(event) {
showLiveRecordingBadge();
// event.data.startedBy — who started it
});
room.addEventListener("room-live-recording-failed", function(event) {
showError("Live recording failed to start");
});
Stop Live Recording
- Method:
EnxRoom.stopLiveRecording(config, Callback) - Event:
room-live-recording-off
room.stopLiveRecording({}, function(resp) {
if (resp.data.status.resultCode === 0) {
console.log("Live recording stopped");
}
});
room.addEventListener("room-live-recording-off", function(event) {
hideLiveRecordingBadge();
});
Watermarking Recorded Files
Watermark a PNG image (max 140×140 px) onto your transcoded recordings. Set it up in Portal: Video → Settings → Recording → Watermarking. Then create the room with "watermark": true:
{
"name": "My Meeting",
"settings": {
"watermark": true
}
}
Individual MKV stream recordings are not watermarked. Live-recording files produced by startLiveRecording() are also not affected by this setting.
Getting Recording Files
EnableX produces three types of output files:
| File Type | Format | Availability |
|---|---|---|
| Individual stream recordings | MKV (per participant) | Minutes after session ends |
| Transcoded composite video | MP4 (single file per segment) | 10–45 minutes post-session (depends on queue) |
| Live-recording file | MP4 | Minutes after session ends |
Retrieve file URLs via the Video API Archives route, or configure automatic delivery to your FTP/S3/Azure/GDrive storage via Portal. EnableX sends a webhook notification when files are ready.
Hard Mute / Unmute a Room
Hard muting silences all participants in the room. Any new participant joining a hard-muted room is automatically muted. Participants cannot unmute themselves — only the moderator can lift the hard mute.
- Mute:
EnxRoom.hardMute(Callback)— Event:hard-mute-room - Unmute:
EnxRoom.hardUnmute(Callback)— Event:hard-unmute-room
// Mute the entire room
room.hardMute(function(result, error) {
// result: { result: 0, msg: "Room is muted" }
});
room.addEventListener("hard-mute-room", function(res) {
showRoomMutedBanner();
// res.moderator — who hard-muted the room
});
// Unmute the entire room
room.hardUnmute(function(result, error) {
// result: { result: 0, msg: "Room is un-muted" }
});
room.addEventListener("hard-unmute-room", function(res) {
hideRoomMutedBanner();
});
Hard Mute / Unmute a Participant
Moderators can silence a specific participant's audio or video, or both. The affected participant cannot unmute themselves until the moderator lifts it.
- Mute audio:
EnxRoom.hardMuteUserAudio(clientId, Callback) - Mute video:
EnxRoom.hardMuteUserVideo(clientId, Callback) - Unmute audio:
EnxRoom.hardUnmuteUserAudio(clientId, Callback) - Unmute video:
EnxRoom.hardUnmuteUserVideo(clientId, Callback)
// Mute a specific participant's audio
room.hardMuteUserAudio(targetClientId, function(response) {
if (response.result === 0) console.log("Participant audio muted");
});
// Mute a specific participant's video
room.hardMuteUserVideo(targetClientId, function(response) {
if (response.result === 0) console.log("Participant video muted");
});
// The affected participant receives:
room.addEventListener("hardmute-user-audio", function(event) {
showForceMutedIndicator();
// event.moderator — who muted you
});
room.addEventListener("hardmute-user-video", function(event) {
showForcedVideoOffIndicator();
});
// Unmute
room.hardUnmuteUserAudio(targetClientId, function(response) {});
room.hardUnmuteUserVideo(targetClientId, function(response) {});
Lock / Unlock a Room
Locking prevents new participants from joining an ongoing session. Existing participants are unaffected. Only the moderator can lock or unlock.
- Lock:
EnxRoom.lock()— Event:room-locked - Unlock:
EnxRoom.unlock()— Event:room-unlocked
room.lock();
room.addEventListener("room-locked", function(event) {
showLockedRoomBadge();
// event carries the moderator ID who locked the room
});
room.unlock();
room.addEventListener("room-unlocked", function(event) {
hideLockedRoomBadge();
});
Moderated Entry (Knock-Enabled Rooms)
In knock-enabled rooms, participants wait for moderator approval before entering. The moderator receives a user-awaited event for each waiting participant and can approve or deny individually.
- Approve:
EnxRoom.approveAwaitedUser(ClientID, Callback) - Deny:
EnxRoom.denyAwaitedUser(ClientID, Callback)
// Moderator is notified when someone is waiting
room.addEventListener("user-awaited", function(event, user) {
// user.clientId, user.name — who is waiting
showApprovalPrompt(user);
});
function approveUser(clientId) {
room.approveAwaitedUser(clientId, function(success, error) {
console.log("User approved:", clientId);
});
}
function denyUser(clientId) {
room.denyAwaitedUser(clientId, function(success, error) {
console.log("User denied:", clientId);
});
}
// The waiting participant receives this when approved:
room.addEventListener("room-allowed", function(event) {
// Now proceed to publish stream and join the session
publishStream();
});
If participants are already waiting when the moderator joins, inspect room.awaitedParticipants immediately after the room-connected event. It is an array of { clientId, name } objects for all pending approvals.
Switch Room Mode
A room defined in group mode can be switched to lecture mode at runtime, and vice versa, without ending the session. When switching to lecture mode, all participant streams are dropped and floor access control activates. When switching back to group mode, participants are notified to republish their streams.
- Method:
EnxRoom.switchRoomMode(roomMode, Callback) - roomMode values:
"group","lecture" - Event:
room-mode-switched
// Switch to lecture mode
room.switchRoomMode("lecture", function(resp) {
if (resp.result === 0) console.log("Switched to lecture mode");
});
room.addEventListener("room-mode-switched", function(event) {
var newMode = event.message.mode; // "lecture" or "group"
if (newMode === "lecture") {
// Participant streams are dropped; floor access control is now active
showLectureModeUI();
} else {
// Prompt participants to republish streams
showPublishPrompt();
}
});
Drop (Force-Disconnect) a User
The moderator can forcibly disconnect one or more participants. Pass an array of client IDs, or an empty array to disconnect everyone.
- Method:
EnxRoom.dropUser(ClientIds, Callback) - Event:
room-disconnected— fired at the affected participant with reason"disconnected-by-moderator"
// Drop a specific participant
room.dropUser([targetClientId], function(res) {
if (res.result === 0) console.log("User dropped");
});
// Drop all participants (moderator stays)
room.dropUser([], function(res) {});
// Affected participant receives:
room.addEventListener("room-disconnected", function(event) {
if (event.message.cause.msg === "disconnected-by-moderator") {
showDroppedMessage();
}
});
Switch Participant Roles
A moderator can promote a participant to moderator role, and the former moderator becomes a participant. The newly appointed moderator immediately gains access to all moderator controls. Role switching can be chained — the new moderator can promote someone else.
- Method:
EnxRoom.switchUserRole(ParticipantId, Callback) - Event:
user-role-changed— broadcast to all
room.switchUserRole(participantClientId, function(status) {
if (status.result === 0) console.log("Role switched");
});
room.addEventListener("user-role-changed", function(event) {
// event.moderator.new — new moderator's client ID
// event.moderator.old — previous moderator's client ID
// event.raisedHands — floor requests (Lecture mode)
// event.approvedHands — floor holders (Lecture mode)
refreshModeratorControls(event);
});
Extend Session Duration
A session's duration is set at room creation. When 10 minutes remain, all participants are notified via conference-remaining-duration and can trigger an extension. The extension window closes once triggered; it reopens at 5 minutes if not extended.
- Method:
EnxRoom.extendConferenceDuration(Callback) - Event:
conference-remaining-duration
room.addEventListener("conference-remaining-duration", function(event) {
var minutesLeft = event.message.timeLeft;
showExtensionPrompt(minutesLeft);
});
function requestExtension() {
room.extendConferenceDuration(function(message) {
if (message.result === 0) {
var grantedMinutes = message.extendedTime;
showExtensionConfirmed(grantedMinutes);
}
});
}
Destroy Session
Moderators call room.destroy() to immediately end the session for all connected participants. All users receive a room-disconnected event with reason "disconnected-by-moderator".
- Method:
EnxRoom.destroy()
room.destroy();
// All participants receive this:
room.addEventListener("room-disconnected", function(event) {
if (event.message.cause.msg === "disconnected-by-moderator") {
showSessionEndedScreen();
}
});
Pin a User
Pinned users appear in the Active Talker list at all times, regardless of whether they are speaking. They are placed after actively talking users in ascending order of activity. The pin limit is max_active_talkers – 1.
- Pin:
EnxRoom.pinUsers(clientIds, Callback) - Unpin:
EnxRoom.unpinUsers(clientIds, Callback) - Event:
updated-pinned-users
// Pin one or more participants
room.pinUsers([clientId1, clientId2], function(resp) {
// resp: { result: 0, clients: ["clientId1", "clientId2"] }
});
room.unpinUsers([clientId1], function(resp) {});
room.addEventListener("updated-pinned-users", function(event) {
// event.moderator_id — who updated pins
// event.clientIds — current list of pinned user IDs
refreshPinnedIndicators(event.clientIds);
});
Spotlight a User
Spotlighting pushes a user to the top of the Active Talker list regardless of activity — they are always front-and-center in the grid. Unlike pinning, spotlighted users appear before actively talking users. Moderators can spotlight up to max_active_talkers users simultaneously.
- Add spotlight:
EnxRoom.addSpotlightUsers(clientIds, Callback) - Remove spotlight:
EnxRoom.removeSpotlightUsers(clientIds, Callback) - Event:
spotlight-users
// Spotlight a presenter
room.addSpotlightUsers([presenterClientId], function(resp) {
// resp: { result: 0, clients: [...] }
});
room.removeSpotlightUsers([presenterClientId], function(resp) {});
room.addEventListener("spotlight-users", function(event) {
// event.moderator_id — who changed spotlight
// event.users — current spotlighted user IDs
refreshSpotlightHighlights(event.users);
});
Spotlight places users at the very top of the Active Talker list — above even actively speaking users. Pin keeps users in the list but below active speakers. Use spotlight for a presenter who must always be prominent; use pin for "always visible" participants who shouldn't dominate the top slot.