Clan Meeting

High-Level Video API

Introduction

 
Most businesses around the world are moving away from conventional methods of interacting with their customers and adapting to technology, which is the need of the hour for sustenance. One such shift is to integrate your business with video conferencing. It increases the ease of doing business while reducing the operating costs by a huge margin.
 
With any such bold business decision, there are technical challenges even for the technology companies to overcome. For situations like these, you can easily integrate Clan Meeting with your web apps using our high-level API, powered by Jitsi. You can be up and running doing what you do best within a few minutes. Even if you do not have any existing website or app and still want to integrate your business with video conferencing, please contact us and we will be happy to assist.

Why Us?

 
Here are a few reasons to choose Clan Meeting API for your video conferencing needs:
 
  1. Hassle Free : The prime reason. So that you can spend your time and energy into growing your business.
  2. Superfast Setup : If you don’t have specific requirements, you can be up and running doing what you do best within half a day.
  3. Scalability & Stability : To handle the sudden influx in the number of customers or being ready for a campaign.
  4. Own Branding : You can have your own logo within the video conferencing call. Also you get a dedicated instance with separate subdomain.
  5. Fresh Look : With a cleaner user interface.
  6. Customization : Need your video recordings to be saved to your SFTP server instead? We can make that happen.
  7. Feature Restrictions : Enable certain video conferencing features only or limit room participants? Yes, possible.
  8. Different Authentication Modes : JWT, LDAP, different auth modes for moderators and participants, or good old username-password.
  9. Integration Assistance : We are there to assist your dev team in case you need any help with the integration.
  10. Pay As You Go : Pay only as per your requirements and usage.
  11. Lowest Rates : Since we have a scalable setup, we can confidently pass on the cost benefits to our clients.
  12. Free Mobile Apps : Make use of Clan Meeting mobile apps to connect to the meetings for a smoother experience without any extra charges.

Installation and Initial Setup

 
Once you contact us, we will understand your requirements and set up an environment as per your needs. We will then send a communication that your environment is ready to use. To integrate your Clan Meeting environment with your application, please include the following JS library. Exact domain name will be shared with you. You would need to use it in the “src” attribute of script tag accordingly. Usually it is your-business-name.clanmeeting.com.
<script src="https://your-business-name.clanmeeting.com/external_api.js"></script> 

Create API Object

 

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); 

Set the HTML DOM Element where video element will be placed

/// 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> 

Pass a JWT token to authenticate your users

 
This is part of onboarding process and the details on how to generate the token for authentication, will be shared separately. As per requirement, a different authentication method can also be opted for.
const options = {
   jwt: "secret_jwt_token",
}; 

Onload event

const options = {
   onload: doStuff(),
};

const api = new JitsiMeetExternalAPI(domain, options);

function doStuff() {
  alert("Press OK to start meeting.");
} 

Set display name and email for the participant

 Note: If JWT authentication is enabled then user info set in the JWT token will be considered.
const options = {
   userInfo: {
        email: "example@email.com",
        displayName: "John Doe"
    } // (optional) JS object containing information about the participant opening the meeting, such as email
}; 

Modify UI components

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
}; 

Control configuration changes for users while creating or joining a meeting

 
All of the below parameters are optional. Please note that these parameters need to be defined inside configOverwrite.
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",
    }
}; 

Useful getters and setters

Capture the screenshot of the large video

api.captureLargeVideoScreenshot().then(dataURL => {
    // save screenshot
}); 

Retrieve a list of available devices

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'
    //     },....]
    // }
    ...
}); 

Retrieve a list with the devices that are currently selected

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'
    //     }
    // }
    ...
}); 

Get participant info

Returns an array containing participants information like participant id, display name, avatar URL and email.

api.getParticipantsInfo(); 

Get current video quality setting

api.getVideoQuality(); 

Device change

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 => {
    ...
}); 

Device list

Resolves with true if the device list is available and with false if not.

api.isDeviceListAvailable().then(isDeviceListAvailable => {
    ...
}); 

Multiple audio input

Resolves with true if multiple audio input is supported and with false if not.

api.isMultipleAudioInputSupported().then(isMultipleAudioInputSupported => {
    ...
}); 

Pin participant

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); 

Resize large video

Resizes the large video container as per the dimensions provided.

api.resizeLargeVideo(width, height); 

Set audio input device

Sets the audio input device to the one with the label or id that is passed.

api.setAudioInputDevice(deviceLabel, deviceId); 

Set audio output device

Sets the audio output device to the one with the label or id that is passed.

api.setAudioOutputDevice(deviceLabel, deviceId); 

Set large video participant

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); 

Set video input device

Sets the video input device to the one with the label or id that is passed.

api.setVideoInputDevice(deviceLabel, deviceId); 

Get number of participants in a conference

const numberOfParticipants = api.getNumberOfParticipants(); 

Get Avatar URL for a participant

const avatarURL = api.getAvatarURL(participantId); 

Get display name of a participant in conference

const displayName = api.getDisplayName(participantId); 

Get email of a participant

const email = api.getEmail(participantId); 

Check whether audio is muted

api.isAudioMuted().then(muted => {
    ...
}); 

Check whether video is muted

api.isVideoMuted().then(muted => {
    ...
}); 

Check whether audio is available

api.isAudioAvailable().then(available => {
    ...
}); 

Check whether video is available

api.isVideoAvailable().then(available => {
    ...
}); 

Execute further commands to control the meeting

List of such commands are provided below.

// Execute single command
api.executeCommand(command, ...arguments);

// Execute multiple commands together
api.executeCommands({
    displayName: [ 'nickname' ],
    toggleAudio: []
}); 

Set display name of local participant

api.executeCommand('displayName', 'New Nickname'); 

Set password for the room / channel

// 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');
}); 

Toggle Lobby on or off

api.addEventListener('participantRoleChanged', function (event) {
    if(event.role === 'moderator') {
        api.executeCommand('toggleLobby', true);
    }
}); 

Play touch tones

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.
}); 

Set subject of the conference (show at top below timer)

api.executeCommand('subject', 'New Conference Subject');

// For no subject add a space
api.executeCommand('subject', ' '); 

Toggle audio

Mutes / unmutes the audio for the local participant.

api.executeCommand('toggleAudio'); 

Toggle video

Mutes / unmutes the video for the local participant.

api.executeCommand('toggleVideo'); 

Toggle chat

Hides / shows the chat window.

api.executeCommand('toggleChat'); 

Toggle screenshare

Starts / stops screen sharing.

api.executeCommand('toggleShareScreen'); 

Toggle tile view

api.executeCommand('toggleTileView'); 

Hang up the call

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'); 

Set local email address

api.executeCommand('email', 'example@example.com'); 

Set local avatar URL

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'); 

Send endpoint text message

Sends a text message to another participant through data channels.

api.executeCommand('sendEndpointTextMessage', 'receiverParticipantId', 'text'); 

Set video quality

Sets the send and receive video quality for the participant. Takes height of resolution as an argument.

api.executeCommand('setVideoQuality', 720); 

Mute everyone

This can only be executed if participant is a moderator.

api.executeCommand('muteEveryone'); 

Listen for events

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); 

Listen for camera error

// Response

{
    type: string, // A constant representing the overall type of the error.
    message: string // Additional information about the error.
} 

Listen for avatar change

{
    id: string, // the id of the participant that changed his avatar.
    avatarURL: string // the new avatar URL.
} 

Listen for audio availability status changes

{
    available: boolean // new available status - boolean
} 

Listen for audio mute status change

{
    muted: boolean // new muted status - boolean
} 

Listen for endpoint text message received through data channel

{
    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
    }
} 

Listen for change in participant displayed in large video

{
    id: string // id of the participant that is now on large video in the stage view.
} 

Listen for mic access errors

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.
} 

Listen for screen sharing on / off by local user

{
    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
    }
} 

Listen for a change in dominant speaker

{
    id: string //participantId of the new dominant speaker
} 

Listen for tile view being entered or exited

{
    enabled: boolean, // whether tile view is not displayed or not
} 

Listen for incoming messages

{
    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
} 

Listen for outgoing messages

{
    message: string // the text of the message
} 

Listen for display name changes

{
    id: string, // the id of the participant that changed his display name
    displayname: string // the new display name
} 

Listen for device list changes

{
    devices: Object 
    // The new list of available devices. 
    // The devices object has the same format as the getAvailableDevices result format.
} 

Listen for email changes

{
    id: string, // the id of the participant that changed his email
    email: string // the new email
} 

Listen for feedback submission for the conference

{
    error: string // The error which occurred during submission, if any.
} 

Listen for new participants joining the meeting

{
    id: string, // the id of the participant
    displayName: string // the display name of the participant
} 

Listen for participant kick events

{
    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
    }
} 

Listen for participants who leave the room

{
    id: string // the id of the participant
} 

Listen for events triggered when role of local user changes (none, moderator, participant)

{
    id: string // the id of the participant
    role: string // the new role of the participant
} 

Listen for password required to join meeting room event

Listen for video conference joined by local 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
} 

Listen for video conference left by local participant

{
    roomName: string // the room name of the conference
} 

Listen for video availability status change

{
    available: boolean // new available status - boolean
} 

Listen for video muted status change

{
    muted: boolean // new muted status - boolean
} 

Listen for video quality settings change

{
    videoQuality: number // the height of the resolution related to the new video quality setting.
} 

Listen for ready to close event

Event notification fired when Clan Meeting is ready to be closed (hang-up operations are completed).

Listen for changes in the subject of the meeting

{
    subject: string // the new subject
} 

Listen for suspend detected

Event notifications about detecting suspend event in host computer.

Remove listeners

// 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'); 

Remove embedded meeting before page unload

api.dispose(); 
Contents