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 covers screen sharing (desktop sharing) implementation using lib-jitsi-meet, including display capture, audio sharing, and screen-specific configurations.
Overview
Screen sharing in lib-jitsi-meet uses the getDisplayMedia API and provides cross-platform support for:
Full desktop sharing : Share entire screen
Window sharing : Share specific application window
Tab sharing : Share browser tab (Chromium-based browsers)
System audio : Capture system audio along with screen (Chrome 104+)
Creating a Screen Share Track
Check if screen sharing is supported
if ( ! JitsiMeetJS . isDesktopSharingEnabled ()) {
console . error ( 'Screen sharing not supported' );
return ;
}
Request screen sharing
JitsiMeetJS . createLocalTracks ({
devices: [ 'desktop' ],
desktopSharingFrameRate: {
min: 5 ,
max: 30
}
}). then ( tracks => {
const desktopTrack = tracks [ 0 ];
console . log ( 'Screen sharing track created' );
// Add to conference
conference . addTrack ( desktopTrack );
}). catch ( error => {
if ( error . name === 'gum.screensharing_user_canceled' ) {
console . log ( 'User canceled screen sharing' );
} else {
console . error ( 'Screen sharing error:' , error );
}
});
Configuration Options
Frame Rate Settings
const options = {
devices: [ 'desktop' ],
// Frame rate configuration
desktopSharingFrameRate: {
min: 5 , // Minimum fps
max: 30 // Maximum fps (higher for motion, lower for static content)
}
};
// Default frame rate is 5 fps (SS_DEFAULT_FRAME_RATE)
JitsiMeetJS . createLocalTracks ( options );
Resolution Settings
const options = {
devices: [ 'desktop' ],
// Resolution constraints
desktopSharingResolution: {
width: {
min: 640 ,
max: 1920
},
height: {
min: 480 ,
max: 1080
}
}
};
Advanced Settings
const options = {
devices: [ 'desktop' ],
// Screen share specific settings
screenShareSettings: {
// Prefer current tab in picker (Chrome 94+)
desktopPreferCurrentTab: false ,
// System audio option (Chrome 105+)
// 'include', 'exclude', or undefined
desktopSystemAudio: 'include' ,
// Allow seamless tab switching (Chrome 107+)
// 'include', 'exclude', or undefined
desktopSurfaceSwitching: 'include' ,
// Preferred display surface
// 'monitor', 'window', 'browser', or undefined
desktopDisplaySurface: 'monitor' ,
// Self browser surface option (Chrome 112+)
// 'include', 'exclude', or undefined
desktopSelfBrowserSurface: 'exclude'
},
// Electron-specific: source types to show in picker
desktopSharingSources: [ 'screen' , 'window' ]
};
Screen Sharing with Audio
Capture System Audio (Chrome 104+)
const options = {
devices: [ 'desktop' ],
screenShareSettings: {
desktopSystemAudio: 'include'
}
};
JitsiMeetJS . createLocalTracks ( options ). then ( tracks => {
tracks . forEach ( track => {
if ( track . getType () === 'video' ) {
console . log ( 'Desktop video track' );
} else if ( track . getType () === 'audio' ) {
console . log ( 'System audio track' );
}
conference . addTrack ( track );
});
});
Audio Quality Settings
const audioQuality = {
// Enable stereo for better system audio
stereo: true ,
// Disable processing for system audio
autoGainControl: false ,
echoCancellation: false ,
noiseSuppression: false ,
// Channel count
channelCount: 2
};
const options = {
devices: [ 'desktop' ],
audioQuality ,
screenShareSettings: {
desktopSystemAudio: 'include'
}
};
Managing Screen Share Tracks
Detect Screen Share
// Check if track is screen share
if ( track . getVideoType () === 'desktop' ) {
console . log ( 'This is a screen share track' );
}
// Get source type
const sourceType = track . sourceType ; // 'screen', 'window', 'browser', etc.
const sourceId = track . sourceId ;
Handle Track Ended
Screen share tracks automatically end when user stops sharing:
desktopTrack . addEventListener (
JitsiMeetJS . events . track . LOCAL_TRACK_STOPPED ,
() => {
console . log ( 'Screen sharing stopped' );
// Remove from conference
conference . removeTrack ( desktopTrack );
// Dispose track
desktopTrack . dispose ();
// Update UI
updateScreenShareButton ( false );
}
);
Stop Screen Sharing Programmatically
function stopScreenShare () {
if ( desktopTrack ) {
conference . removeTrack ( desktopTrack ). then (() => {
desktopTrack . dispose ();
desktopTrack = null ;
console . log ( 'Screen sharing stopped' );
});
}
}
Content Hint
Optimize encoding based on content type:
// The library automatically sets contentHint based on frame rate
// High fps (>5): 'motion' - optimized for video content
// Low fps (≤5): 'detail' - optimized for text/images
// Manual override (if needed)
const mediaStreamTrack = desktopTrack . track ;
if ( 'contentHint' in mediaStreamTrack ) {
// For presentations/documents
mediaStreamTrack . contentHint = 'detail' ;
// For video playback
mediaStreamTrack . contentHint = 'motion' ;
// For mixed content
mediaStreamTrack . contentHint = 'text' ;
}
Chrome/Chromium
Modern Chrome
Legacy Chrome
const options = {
devices: [ 'desktop' ],
desktopSharingFrameRate: { min: 5 , max: 30 },
screenShareSettings: {
desktopSystemAudio: 'include' ,
desktopSurfaceSwitching: 'include' ,
desktopPreferCurrentTab: false ,
desktopSelfBrowserSurface: 'exclude'
}
};
Firefox
const options = {
devices: [ 'desktop' ],
desktopSharingFrameRate: { min: 5 , max: 30 },
// Firefox supports basic getDisplayMedia
// No system audio support
};
Safari
const options = {
devices: [ 'desktop' ],
desktopSharingFrameRate: { min: 5 , max: 30 },
screenShareSettings: {
// Safari supports displaySurface preference
desktopDisplaySurface: 'monitor'
}
};
Electron
const options = {
devices: [ 'desktop' ],
// Source types to show in picker
desktopSharingSources: [ 'screen' , 'window' ],
// Frame rate and resolution
desktopSharingFrameRate: { min: 5 , max: 30 },
desktopSharingResolution: {
width: { max: 1920 },
height: { max: 1080 }
}
};
// Electron uses custom desktop picker
// Configured via JitsiMeetScreenObtainer.openDesktopPicker
Advanced Use Cases
Replace Camera with Screen Share
async function switchToScreenShare () {
try {
// Create screen share track
const [ desktopTrack ] = await JitsiMeetJS . createLocalTracks ({
devices: [ 'desktop' ],
desktopSharingFrameRate: { min: 5 , max: 30 }
});
// Find existing video track
const cameraTrack = localTracks . find (
t => t . getType () === 'video' && t . getVideoType () === 'camera'
);
if ( cameraTrack ) {
// Replace camera with screen share
await conference . replaceTrack ( cameraTrack , desktopTrack );
cameraTrack . dispose ();
// Update tracks array
const index = localTracks . indexOf ( cameraTrack );
localTracks [ index ] = desktopTrack ;
} else {
// Just add screen share
await conference . addTrack ( desktopTrack );
localTracks . push ( desktopTrack );
}
// Handle track stopped
desktopTrack . addEventListener (
JitsiMeetJS . events . track . LOCAL_TRACK_STOPPED ,
() => switchBackToCamera ()
);
} catch ( error ) {
console . error ( 'Failed to share screen:' , error );
}
}
async function switchBackToCamera () {
const [ cameraTrack ] = await JitsiMeetJS . createLocalTracks ({
devices: [ 'video' ]
});
const desktopTrack = localTracks . find (
t => t . getType () === 'video' && t . getVideoType () === 'desktop'
);
if ( desktopTrack ) {
await conference . replaceTrack ( desktopTrack , cameraTrack );
desktopTrack . dispose ();
const index = localTracks . indexOf ( desktopTrack );
localTracks [ index ] = cameraTrack ;
}
}
Share Camera and Screen Simultaneously
async function shareScreenAndCamera () {
// Note: Check browser support for multiple video tracks
const [ desktopTrack ] = await JitsiMeetJS . createLocalTracks ({
devices: [ 'desktop' ],
desktopSharingFrameRate: { min: 5 , max: 30 }
});
// Add as second video track
await conference . addTrack ( desktopTrack );
localTracks . push ( desktopTrack );
// Both camera and screen share are now active
console . log ( 'Sharing camera and screen' );
}
Dynamic Frame Rate Adjustment
// Adjust frame rate based on content
function setScreenShareFrameRate ( maxFps ) {
// Set globally for future screen shares
JitsiMeetJS . setDesktopSharingFrameRate ( maxFps );
// Or apply to existing track
if ( desktopTrack ) {
const track = desktopTrack . track ;
track . applyConstraints ({
frameRate: { max: maxFps , min: 5 }
}). then (() => {
console . log ( 'Frame rate updated to' , maxFps );
});
}
}
// Use lower fps for presentations
setScreenShareFrameRate ( 5 );
// Use higher fps for video playback
setScreenShareFrameRate ( 30 );
Error Handling
JitsiMeetJS . createLocalTracks ({ devices: [ 'desktop' ] })
. then ( tracks => {
// Success
})
. catch ( error => {
switch ( error . name ) {
case 'gum.screensharing_user_canceled' :
console . log ( 'User canceled screen sharing' );
break ;
case 'gum.permission_denied' :
console . error ( 'Screen sharing permission denied' );
break ;
case 'gum.screensharing_not_supported' :
console . error ( 'Screen sharing not supported' );
break ;
case 'gum.electron_desktop_picker_not_found' :
console . error ( 'Electron desktop picker not available' );
break ;
case 'gum.electron_desktop_picker_error' :
console . error ( 'Electron desktop picker error' );
break ;
default :
console . error ( 'Screen sharing error:' , error );
}
});
Best Practices
Optimize frame rate for content type
Use low frame rates (5 fps) for static content like presentations and documents. Use higher frame rates (15-30 fps) for video playback or animations. // Static content
desktopSharingFrameRate : { min : 5 , max : 5 }
// Video content
desktopSharingFrameRate : { min : 15 , max : 30 }
Handle track stopped event
Always listen for the LOCAL_TRACK_STOPPED event to update UI when user stops sharing: desktopTrack . addEventListener (
JitsiMeetJS . events . track . LOCAL_TRACK_STOPPED ,
handleScreenShareStopped
);
Check browser capabilities
const supportsSystemAudio =
JitsiMeetJS . browser . isChromiumBased () &&
JitsiMeetJS . browser . isEngineVersionGreaterThan ( 104 );
if ( supportsSystemAudio ) {
// Enable system audio option
}
Next Steps
Audio/Video Quality Control encoding quality
Recording Record conferences and screen shares