<script src="https://your-business-name.clanmeeting.com/external_api.js"></script>
As stated earlier, our API’s are powered by Jitsi Meet so that you can integrate Clan Meeting environment with your application. The next step for embedding Clan Meeting is to create the API object. Its constructor takes a number of options:
domain: Domain name provided by us.
options: Optional arguments that can be passed along. Please keep reading for the list of such optional parameters. roomName is the only parameter that needs to be passed to create a meeting room.
Example:
const domain = "your-business-name.clanmeeting.com";
const options = {
roomName: "ClanMeetingTestRoom", // Set the name of the room. The same will reflect in the meeting URL also.
<parameter2>: <value>,
<parameter3>: <value>,
...
};
const api = new JitsiMeetExternalAPI(domain, options);
/// Complete basic example
<!DOCTYPE html>
<html>
<body>
// Edit the style tag to set the height, width and position of video meeting element
<div id = "mydiv" style="position:fixed; top:0; left:0; bottom:0; right:0; width:100%; height:50%; border:none; margin:0; padding:0; overflow:hidden; z-index:999999;"></div>
<script src='https://your-business-name.clanmeeting.com/external_api.js'></script>
<script>
const domain = "your-business-name.clanmeeting.com";
const options = {
roomName: "YetAnotherComplexRoomName",
parentNode: document.querySelector('#mydiv'),
};
const api = new JitsiMeetExternalAPI(domain, options);
</script>
</body>
</html>
const options = {
jwt: "secret_jwt_token",
};
const options = {
onload: doStuff(),
};
const api = new JitsiMeetExternalAPI(domain, options);
function doStuff() {
alert("Press OK to start meeting.");
}
const options = {
userInfo: {
email: "example@email.com",
displayName: "John Doe"
} // (optional) JS object containing information about the participant opening the meeting, such as email
};
All of the below parameters are optional. The parameter values mentioned below are the default values. Please note that these parameters need to be defined inside interfaceConfigOverwrite.
const options = {
... // Other parameters
interfaceConfigOverwrite {
/**
* Whether the connection indicator icon should hide itself based on
* connection strength. If true, the connection indicator will remain
* displayed while the participant has a weak connection and will hide
* itself after the CONNECTION_INDICATOR_HIDE_TIMEOUT when the connection is
* strong.
*
* @type {boolean}
*/
CONNECTION_INDICATOR_AUTO_HIDE_ENABLED: true,
/**
* How long the connection indicator should remain displayed before hiding.
* Used in conjunction with CONNECTION_INDICATOR_AUTOHIDE_ENABLED.
*
* @type {number}
*/
CONNECTION_INDICATOR_AUTO_HIDE_TIMEOUT: 5000,
/**
* If true, hides the connection indicators completely.
*
* @type {boolean}
*/
CONNECTION_INDICATOR_DISABLED: false,
DEFAULT_BACKGROUND: '#2E496A',
DEFAULT_LOCAL_DISPLAY_NAME: 'me',
DEFAULT_REMOTE_DISPLAY_NAME: 'Participant',
DISABLE_DOMINANT_SPEAKER_INDICATOR: false,
/**
* If true, notifications regarding joining/leaving are no longer displayed.
*/
DISABLE_JOIN_LEAVE_NOTIFICATIONS: true,
/**
* Whether to only show the filmstrip (and hide the toolbar).
*/
filmStripOnly: false,
/**
* Hide the invite prompt in the header when alone in the meeting.
*/
HIDE_INVITE_MORE_HEADER: true,
INITIAL_TOOLBAR_TIMEOUT: 10000,
/**
* Maximum coefficient of the ratio of the large video to the visible area
* after the large video is scaled to fit the window.
*
* @type {number}
*/
MAXIMUM_ZOOMING_COEFFICIENT: 1.3,
// Names of browsers which should show a warning stating the current browser
// has a suboptimal experience. Browsers which are not listed as optimal or
// unsupported are considered suboptimal. Valid values are:
// chrome, chromium, edge, electron, firefox, nwjs, opera, safari
OPTIMAL_BROWSERS: [ 'chrome', 'chromium', 'firefox', 'nwjs', 'electron', 'safari' ],
/**
* Decides whether the chrome extension banner should be rendered on the landing page and during the meeting.
* If this is set to false, the banner will not be rendered at all. If set to true, the check for extension(s)
* being already installed is done before rendering.
*/
SHOW_CHROME_EXTENSION_BANNER: false,
/**
* The name of the toolbar buttons to display in the toolbar, including the
* "More actions" menu. If present, the button will display. Exceptions are
* "livestreaming" and "recording" which also require being a moderator and
* needs to be enabled specifically for your environment. Also, the "profile"
* button will not display for users with a JWT.
* Notes:
* - it's impossible to choose which buttons go in the "More actions" menu
* - it's impossible to control the placement of buttons
* - 'desktop' controls the "Share your screen" button
*/
TOOLBAR_BUTTONS: [
'microphone', 'camera', 'closedcaptions', 'desktop', 'fullscreen',
'fodeviceselection', 'hangup', 'chat', 'recording',
'livestreaming', 'etherpad', 'sharedvideo', 'raisehand',
'videoquality', 'filmstrip', 'invite', 'feedback', 'stats', 'shortcuts',
'tileview', 'download', 'help', 'mute-everyone', 'security', 'settings'
],
TOOLBAR_TIMEOUT: 4000,
// Browsers, in addition to those which do not fully support WebRTC, that
// are not supported and should show the unsupported browser page.
UNSUPPORTED_BROWSERS: [],
/**
* Whether to show thumbnails in filmstrip as a column instead of as a row.
*/
VERTICAL_FILMSTRIP: false,
// Determines how the video would fit the screen. 'both' would fit the whole
// screen, 'height' would fit the original video height to the height of the
// screen, 'width' would fit the original video width to the width of the
// screen respecting ratio.
VIDEO_LAYOUT_FIT: 'both',
/**
* When enabled, the kick participant button will not be presented for users without a JWT
*/
HIDE_KICK_BUTTON_FOR_GUESTS: true,
/**
* How many columns the tile view can expand to. The respected range is
* between 1 and 5.
*/
TILE_VIEW_MAX_COLUMNS: 5,
/**
* Override the behavior of some notifications to remain displayed until
* explicitly dismissed through a user action. The value is how long, in
* milliseconds, those notifications should remain displayed.
*/
ENFORCE_NOTIFICATION_AUTO_DISMISS_TIMEOUT: 10000,
},
... // Other parameters
};
const options = {
... // Other parameters
configOverwrite {
/**
* If set to true all muting operations
* of remote participants will be disabled.
*/
disableRemoteMute: false, // This is a moderator privilege
/**
* Hide the Yellow Insecure Room
* name warning button from top right corner
*/
enableInsecureRoomNameWarning: true,
/**
* Show a warning when you are
* trying to talk while on mute
*/
enableTalkWhileMuted: true,
/// Hides Lobby Button
hideLobbyButton: true,
/**
* Enables a pre-joining page where users can select
* mic, camera and name settings before joining meeting
*/
prejoinPageEnabled: false,
/// Makes display name mandatory to be entered by all participants
requireDisplayName: true,
/// Disable kick participant option
remoteVideoMenu: {
disableKick: true // This is a moderator privilege
},
/**
* When enabled the password used for locking a room is
* restricted to up to the number of digits specified
*/
roomPasswordNumberOfDigits: 10, // default: roomPasswordNumberOfDigits: false,
/**
* Start the conference in audio only mode (no video is
* being received nor sent).
*/
startAudioOnly: false,
/// Every participant after the Nth will start audio muted.
startAudioMuted: 10,
/**
* Start calls with audio muted. Unlike the option
* above, this one is only applied locally.
*/
startWithAudioMuted: false,
/// Try to start calls with screen-sharing instead of camera video.
startScreenSharing: false,
/// Every participant after the Nth will start video muted.
startVideoMuted: 10,
/**
* Start calls with video muted. Unlike the option above,
* this one is only applied locally.
*/
startWithVideoMuted: false,
/**
* Set subject for the meeting
* By default the subject = roomName.
* If you want to disable subject, set it to an empty string i.e. ""
*/
subject: "Project Updates",
}
};
api.captureLargeVideoScreenshot().then(dataURL => {
// save screenshot
});
api.getAvailableDevices().then(devices => {
// devices = {
// audioInput: [{
// deviceId: 'ID'
// groupId: 'grpID'
// kind: 'audioinput'
// label: 'label'
// },....],
// audioOutput: [{
// deviceId: 'ID'
// groupId: 'grpID'
// kind: 'audioOutput'
// label: 'label'
// },....],
// videoInput: [{
// deviceId: 'ID'
// groupId: 'grpID'
// kind: 'videoInput'
// label: 'label'
// },....]
// }
...
});
api.getCurrentDevices().then(devices => {
// devices = {
// audioInput: {
// deviceId: 'ID'
// groupId: 'grpID'
// kind: 'videoInput'
// label: 'label'
// },
// audioOutput: {
// deviceId: 'ID'
// groupId: 'grpID'
// kind: 'videoInput'
// label: 'label'
// },
// videoInput: {
// deviceId: 'ID'
// groupId: 'grpID'
// kind: 'videoInput'
// label: 'label'
// }
// }
...
});
Returns an array containing participants information like participant id, display name, avatar URL and email.
api.getParticipantsInfo();
api.getVideoQuality();
Resolves with true if the device change is available and with false if not.
// The accepted deviceType values are - 'output', 'input' or undefined.
api.isDeviceChangeAvailable(deviceType).then(isDeviceChangeAvailable => {
...
});
Resolves with true if the device list is available and with false if not.
api.isDeviceListAvailable().then(isDeviceListAvailable => {
...
});
Resolves with true if multiple audio input is supported and with false if not.
api.isMultipleAudioInputSupported().then(isMultipleAudioInputSupported => {
...
});
Elects the participant with the given id to be the pinned participant in order to always receive video for this participant (even if lastN is enabled).
api.pinParticipant(participantId);
Resizes the large video container as per the dimensions provided.
api.resizeLargeVideo(width, height);
Sets the audio input device to the one with the label or id that is passed.
api.setAudioInputDevice(deviceLabel, deviceId);
Sets the audio output device to the one with the label or id that is passed.
api.setAudioOutputDevice(deviceLabel, deviceId);
Displays the participant with the participant id (Jid) that is passed on the large video. If no participant id is passed, a participant will be picked based on the dominant / pinned speaker settings.
api.setLargeVideoParticipant(participantId);
OR
api.executeCommand('setLargeVideoParticipant', participantId);
Sets the video input device to the one with the label or id that is passed.
api.setVideoInputDevice(deviceLabel, deviceId);
const numberOfParticipants = api.getNumberOfParticipants();
const avatarURL = api.getAvatarURL(participantId);
const displayName = api.getDisplayName(participantId);
const email = api.getEmail(participantId);
api.isAudioMuted().then(muted => {
...
});
api.isVideoMuted().then(muted => {
...
});
api.isAudioAvailable().then(available => {
...
});
api.isVideoAvailable().then(available => {
...
});
List of such commands are provided below.
// Execute single command
api.executeCommand(command, ...arguments);
// Execute multiple commands together
api.executeCommands({
displayName: [ 'nickname' ],
toggleAudio: []
});
api.executeCommand('displayName', 'New Nickname');
// Set new password for channel
api.addEventListener('participantRoleChanged', function(event) {
if (event.role === "moderator") {
api.executeCommand('password', 'The Password');
}
});
// Join a protected channel
api.on('passwordRequired', function ()
{
api.executeCommand('password', 'The Password');
});
api.addEventListener('participantRoleChanged', function (event) {
if(event.role === 'moderator') {
api.executeCommand('toggleLobby', true);
}
});
api.executeCommand('sendTones', {
tones: string, // The dial pad touch tones to play. For example, '12345#'.
duration: number, // Optional. The number of milliseconds each tone should play. The default is 200.
pause: number // Optional. The number of milliseconds between each tone. The default is 200.
});
api.executeCommand('subject', 'New Conference Subject');
// For no subject add a space
api.executeCommand('subject', ' ');
Mutes / unmutes the audio for the local participant.
api.executeCommand('toggleAudio');
Mutes / unmutes the video for the local participant.
api.executeCommand('toggleVideo');
Hides / shows the chat window.
api.executeCommand('toggleChat');
Starts / stops screen sharing.
api.executeCommand('toggleShareScreen');
api.executeCommand('toggleTileView');
Please note that there is no direct way to end the meeting for everyone. This will hang up meeting for the local participant.
api.executeCommand('hangup');
api.executeCommand('email', 'example@example.com');
Note: Avatars need to be stored in either Gravatar or Libravatar and cannot be stored locally. This is a privacy concern for few of our clients. We request you to check your data laws and privacy policy before proceeding to use this feature.
api.executeCommand('avatarUrl', 'https://www.gravatar.com/avatar/db1a33946e2a8577b8d3377d0715bf61?s=130&d=identicon');
Sends a text message to another participant through data channels.
api.executeCommand('sendEndpointTextMessage', 'receiverParticipantId', 'text');
Sets the send and receive video quality for the participant. Takes height of resolution as an argument.
api.executeCommand('setVideoQuality', 720);
This can only be executed if participant is a moderator.
api.executeCommand('muteEveryone');
You can add event listeners to the embedded meeting using the EventEmitter methods (addListener or on).
/**
* The event parameter is a String object with the name of the event.
* The listener parameter is a Function object with one argument that will
* be notified when the event occurs with data related to the event.
**/
api.on(eventName, listener);
OR
api.addListener(eventName, listener);
// In case you are using older version of Clan Meeting. To be deprecated.
api.addEventListener(event, listener);
// Response
{
type: string, // A constant representing the overall type of the error.
message: string // Additional information about the error.
}
{
id: string, // the id of the participant that changed his avatar.
avatarURL: string // the new avatar URL.
}
{
available: boolean // new available status - boolean
}
{
muted: boolean // new muted status - boolean
}
{
senderInfo: {
jid: string, // the jid of the sender
id: string // the participant id of the sender
},
eventData: {
name: string // the name of the datachannel event: `endpoint-text-message`
text: string // the received text from the sender
}
}
{
id: string // id of the participant that is now on large video in the stage view.
}
Fired if Clan Meeting was not able to access microphone.
{
type: string, // A constant representing the overall type of the error.
message: string // Additional information about the error.
}
{
on: boolean, //whether screen sharing is on
details: {
// From where the screen sharing is capturing, if known. Values which are
// passed include 'window', 'screen', 'proxy', 'device'. The value undefined
// will be passed if the source type is unknown or screen share is off.
sourceType: string|undefined
}
}
{
id: string //participantId of the new dominant speaker
}
{
enabled: boolean, // whether tile view is not displayed or not
}
{
from: string, // The id of the user that sent the message
nick: string, // the nickname of the user that sent the message
message: string // the text of the message
}
{
message: string // the text of the message
}
{
id: string, // the id of the participant that changed his display name
displayname: string // the new display name
}
{
devices: Object
// The new list of available devices.
// The devices object has the same format as the getAvailableDevices result format.
}
{
id: string, // the id of the participant that changed his email
email: string // the new email
}
{
error: string // The error which occurred during submission, if any.
}
{
id: string, // the id of the participant
displayName: string // the display name of the participant
}
{
kicked: {
id: string, // the id of the participant removed from the room
local: boolean // whether or not the participant is the local particiapnt
},
kicker: {
id: string // the id of the participant who kicked out the other participant
}
}
{
id: string // the id of the participant
}
{
id: string // the id of the participant
role: string // the new role of the participant
}
{
roomName: string, // the room name of the conference
id: string, // the id of the local participant
displayName: string, // the display name of the local participant
avatarURL: string // the avatar URL of the local participant
}
{
roomName: string // the room name of the conference
}
{
available: boolean // new available status - boolean
}
{
muted: boolean // new muted status - boolean
}
{
videoQuality: number // the height of the resolution related to the new video quality setting.
}
Event notification fired when Clan Meeting is ready to be closed (hang-up operations are completed).
{
subject: string // the new subject
}
Event notifications about detecting suspend event in host computer.
// Remove all listeners
api.removeAllListeners([eventName1, eventName2 ...]);
// Or one by one
api.removeListener(eventName, listener);
// Example
const callback = (stream) => {
console.log('someone connected!');
};
server.on('connection', callback);
// ...
server.removeListener('connection', callback);
// If you are using older version of Clan Meeting. To be deprecated.
// To add multiple listeners at once
function incomingMessageListener(object)
{
// ...
}
function outgoingMessageListener(object)
{
// ...
}
api.addEventListeners({
incomingMessage: incomingMessageListener,
outgoingMessage: outgoingMessageListener
});
// To remove all listeners
api.removeEventListeners([ 'incomingMessage', 'outgoingMessageListener' ]);
// To remove one by one
api.removeEventListener('incomingMessage');
api.dispose();