Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/jitsi/lib-jitsi-meet/llms.txt

Use this file to discover all available pages before exploring further.

This guide shows you how to create conferences, manage participants, and handle conference lifecycle events using the JitsiConference class.

Creating a Conference

1

Establish a connection

First, ensure you have an active connection:
const connection = new JitsiMeetJS.JitsiConnection(null, null, options);
connection.connect();
2

Create conference instance

Once connected, create a conference:
const conferenceOptions = {
    openBridgeChannel: true,
    p2p: {
        enabled: true,
        preferredCodec: 'VP9',
        backToP2PDelay: 5
    },
    startAudioMuted: 10,
    startVideoMuted: 10
};

const conference = connection.initJitsiConference(
    'room-name',
    conferenceOptions
);
3

Register event listeners

Attach handlers for conference events:
conference.on(JitsiMeetJS.events.conference.CONFERENCE_JOINED, onConferenceJoined);
conference.on(JitsiMeetJS.events.conference.USER_JOINED, onUserJoined);
conference.on(JitsiMeetJS.events.conference.USER_LEFT, onUserLeft);
conference.on(JitsiMeetJS.events.conference.TRACK_ADDED, onTrackAdded);
conference.on(JitsiMeetJS.events.conference.TRACK_REMOVED, onTrackRemoved);
4

Join the conference

Join the conference room:
conference.join();

Conference Configuration

Core Options

interface IConferenceOptions {
    config: {
        // P2P configuration
        p2p?: {
            enabled?: boolean;
            backToP2PDelay?: number;           // Delay before switching back to P2P (default: 5s)
            codecPreferenceOrder?: string[];    // e.g., ['VP9', 'VP8', 'H264']
            preferredCodec?: string;
        };
        
        // Start muted policies
        startAudioMuted?: number;              // Mute audio after N participants
        startVideoMuted?: number;              // Mute video after N participants
        
        // Quality settings
        channelLastN?: number;                 // Number of video streams to receive (-1 for all)
        startLastN?: number;                   // Initial lastN value
        
        // E2EE
        e2eping?: {
            enabled?: boolean;
        };
        
        // Statistics
        statisticsId?: string;                 // User identifier for stats
        statisticsDisplayName?: string;        // Display name for stats
    };
}

Video Quality Configuration

const conferenceOptions = {
    videoQuality: {
        codecPreferenceOrder: ['VP9', 'VP8', 'H264'],
        preferredCodec: 'VP9',
        screenshareCodec: 'VP9',
        enableAdaptiveMode: true,
        disabledCodec: 'H264'
    }
};

Event Handling

function onConferenceJoined() {
    console.log('Conference joined!');
    console.log('Participant ID:', conference.myUserId());
    
    // Add local tracks
    localTracks.forEach(track => {
        conference.addTrack(track);
    });
}

Managing Participants

Get Participant Information

// Get all participants
const participants = conference.getParticipants();

// Get specific participant
const participant = conference.getParticipantById(participantId);

// Get participant properties
const displayName = participant.getDisplayName();
const role = participant.getRole();
const status = participant.getStatus();

Participant Roles

// Check if participant is moderator
if (participant.isModerator()) {
    console.log('Participant is a moderator');
}

// Check if participant is hidden (e.g., recorder)
if (participant.isHidden()) {
    console.log('Participant is hidden');
}

// Grant moderator role (requires moderator privileges)
conference.grantOwner(participantId);

// Kick participant (requires moderator privileges)
conference.kickParticipant(participantId);

Managing Tracks

Add Local Tracks

// Create local tracks
JitsiMeetJS.createLocalTracks({
    devices: ['audio', 'video']
}).then(tracks => {
    tracks.forEach(track => {
        // Add track to conference
        conference.addTrack(track).catch(error => {
            console.error('Failed to add track:', error);
        });
    });
});

Remove Tracks

// Remove specific track
conference.removeTrack(localVideoTrack).then(() => {
    localVideoTrack.dispose();
}).catch(error => {
    console.error('Failed to remove track:', error);
});

Replace Tracks

// Replace video track (e.g., switch camera)
conference.replaceTrack(oldVideoTrack, newVideoTrack).then(() => {
    console.log('Track replaced successfully');
    oldVideoTrack.dispose();
}).catch(error => {
    console.error('Failed to replace track:', error);
});

Audio/Video Moderation

Mute/Unmute Participants

// Mute participant's audio (requires moderator)
conference.muteParticipant(participantId, MediaType.AUDIO);

// Request participant to unmute
conference.sendCommandOnce('unmute-request', {
    attributes: { participantId }
});

Handle Mute Events

conference.on(
    JitsiMeetJS.events.conference.TRACK_MUTE_CHANGED,
    (track) => {
        if (track.isMuted()) {
            console.log('Track muted:', track.getType());
        } else {
            console.log('Track unmuted:', track.getType());
        }
    }
);

Dominant Speaker

Track Dominant Speaker

conference.on(
    JitsiMeetJS.events.conference.DOMINANT_SPEAKER_CHANGED,
    (participantId) => {
        console.log('Dominant speaker:', participantId);
        
        const participant = conference.getParticipantById(participantId);
        if (participant) {
            console.log('Name:', participant.getDisplayName());
        }
    }
);

Last N

Control how many video streams to receive:
// Receive up to 5 video streams
conference.setLastN(5);

// Receive all video streams
conference.setLastN(-1);

// Get current lastN value
const lastN = conference.getLastN();

Properties and Commands

Set Local Properties

// Set display name
conference.setDisplayName('John Doe');

// Set custom property
conference.setLocalParticipantProperty('region', 'us-west');
conference.setLocalParticipantProperty('avatarUrl', 'https://...');

Send Commands

// Send custom command
conference.sendCommand('custom-action', {
    attributes: { data: 'value' },
    value: 'message'
});

// Send command once
conference.sendCommandOnce('one-time-action', {
    attributes: { key: 'value' }
});

// Receive commands
conference.addCommandListener('custom-action', (data, from) => {
    console.log('Command from:', from);
    console.log('Data:', data);
});

Leaving a Conference

1

Remove local tracks

localTracks.forEach(track => {
    conference.removeTrack(track);
    track.dispose();
});
2

Leave the conference

conference.leave().then(() => {
    console.log('Left conference successfully');
}).catch(error => {
    console.error('Error leaving conference:', error);
});
3

Clean up listeners

conference.off(JitsiMeetJS.events.conference.CONFERENCE_JOINED, onConferenceJoined);
conference.off(JitsiMeetJS.events.conference.USER_JOINED, onUserJoined);
// ... remove other listeners

Advanced Features

Sender Video Constraints

Set constraints for video encoding:
conference.setSenderVideoConstraint(720); // Set max resolution to 720p

Receiver Video Constraints

Control received video quality per participant:
const constraints = {
    'participant-id-1': { maxHeight: 720 },
    'participant-id-2': { maxHeight: 180 }
};

conference.setReceiverConstraints(constraints);

Speaker Statistics

Get speaking time statistics:
conference.on(
    JitsiMeetJS.events.conference.SPEAKER_STATS_RECEIVED,
    (stats) => {
        // stats is an object with participant IDs as keys
        Object.keys(stats).forEach(participantId => {
            const { displayName, totalDominantSpeakerTime } = stats[participantId];
            console.log(`${displayName} spoke for ${totalDominantSpeakerTime}ms`);
        });
    }
);

Next Steps

Handling Media Tracks

Learn about track management

Screen Sharing

Enable screen sharing in your app

Build docs developers (and LLMs) love