Screen Sharing Solutions for Hybrid Meetings

Building effective screen sharing into your meeting platform requires understanding the technical tradeoffs between different approaches. Whether you’re integrating with an existing video conferencing service or building custom functionality, this guide covers the practical implementation details developers need to know.

Understanding Screen Sharing Protocols

Screen sharing fundamentally involves capturing display content, encoding it efficiently, and transmitting it to participants. The three main approaches are desktop capture APIs, WebRTC-based streaming, and server-side rendering with streaming.

Desktop capture using the Screen Capture API works directly in browsers and provides the quickest path to implementation. WebRTC offers lower latency for real-time collaboration but requires more setup. Server-side rendering handles the most complex scenarios but adds infrastructure costs.

Browser-Based Screen Capture

Modern browsers support screen capture through the getDisplayMedia() API. This method requires user permission but works without additional software installation.

Here’s a basic implementation:

async function startScreenShare() {
  try {
    const stream = await navigator.mediaDevices.getDisplayMedia({
      video: {
        displaySurface: 'monitor', // 'monitor', 'window', or 'browser'
        width: { ideal: 1920 },
        height: { ideal: 1080 },
        frameRate: { ideal: 30 }
      },
      audio: false
    });
    
    // Handle user stopping share via browser UI
    stream.getVideoTracks()[0].addEventListener('ended', () => {
      console.log('Screen share ended by user');
    });
    
    return stream;
  } catch (err) {
    console.error('Screen share failed:', err);
  }
}

The displaySurface option lets you control whether users share their entire monitor, a specific window, or a browser tab. For hybrid meetings, encouraging window sharing often works better than full-screen capture since it avoids exposing notifications and sensitive information.

WebRTC-Based Screen Sharing

WebRTC provides peer-to-peer delivery with minimal latency, making it suitable for interactive sessions where delay matters. Most WebRTC implementations support screen sharing as an additional video track.

Integrating screen sharing with an existing WebRTC setup involves adding a second video track to your connection:

async function addScreenShareToPeerConnection(pc, stream) {
  const videoTrack = stream.getVideoTracks()[0];
  
  // Replace existing video track or add new one
  const sender = pc.getSenders().find(s => 
    s.track && s.track.kind === 'video'
  );
  
  if (sender) {
    await sender.replaceTrack(videoTrack);
  } else {
    pc.addTrack(videoTrack);
  }
  
  // Handle resolution changes during share
  videoTrack.onended = () => {
    // Restore camera video
    restoreCameraVideo(pc);
  };
}

WebRTC screen sharing works well when you control both the sender and receiver. However, compatibility varies across browsers and requires fallback handling for edge cases.

Third-Party API Integrations

Building screen sharing from scratch works for specialized use cases, but most teams benefit from integrating established services. Several providers offer screen sharing as part of their video conferencing APIs.

Daily.co Screen Sharing

Daily.co provides a straightforward screen sharing API that handles cross-browser compatibility:

import DailyIframe from '@daily-co/daily-js';

const callFrame = DailyIframe.createFrame({
  iframeStyle: {
    width: '100%',
    height: '600px',
    border: '0'
  },
  showLeaveButton: true
});

callFrame.join({ url: 'https://your-domain.daily.co/room' });

// Enable screen sharing
document.getElementById('share-screen').onclick = () => {
  callFrame.startScreenShare();
};

Their API handles the complexity of different browser implementations and provides a consistent interface across platforms.

LiveKit Screen Sharing

LiveKit offers a more developer-focused approach with fine-grained control over media streams. Their SDK supports both browser-based capture and server-side screen recording:

import { Room, VideoPresets } from 'livekit-client';

const room = new Room({
  adaptiveStream: true,
  dynacast: true
});

await room.connect('wss://your-server.com', 'room-token');

// Publish screen share with specific encoding
await room.localParticipant.enableScreenShare({
  videoCodec: 'vp8',
  resolution: VideoPresets.h720.resolution
});

LiveKit works well when you need custom UI or want to process screen share content server-side for recording or analysis.

Optimizing for Developer Workflows

Hybrid meetings for developer teams often involve code review, terminal output, and architecture diagrams. Optimizing your screen sharing setup for these scenarios improves meeting effectiveness.

Resolution and Frame Rate Tradeoffs

Higher resolution and frame rate provide clearer detail but increase bandwidth requirements. For code review sessions, 1080p at 15fps typically suffices. Terminal scrolling looks smooth at 30fps, while animations or demos benefit from 60fps.

Configure your capture settings based on content type:

const contentSettings = {
  codeReview: {
    width: 1920,
    height: 1080,
    frameRate: 15 // Higher resolution, lower frame rate
  },
  terminal: {
    width: 1280,
    height: 720,
    frameRate: 30 // Lower resolution, smooth motion
  },
  presentation: {
    width: 1920,
    height: 1080,
    frameRate: 30 // Balanced settings
  }
};

function getCaptureSettings(useCase) {
  return contentSettings[useCase] || contentSettings.presentation;
}

Audio Considerations

Screen sharing typically doesn’t include system audio by default. If you need to share sound (for videos or demonstrations), enable audio capture:

const stream = await navigator.mediaDevices.getDisplayMedia({
  video: true,
  audio: true // Request system audio (not supported everywhere)
});

System audio support varies significantly across browsers and operating systems. Always provide fallback instructions when audio sharing is critical.

Building Custom Solutions

For teams with specific requirements, building custom screen sharing infrastructure provides maximum flexibility. This approach requires more engineering investment but enables unique features.

A basic custom implementation using WebRTC involves three components: a signaling server, an SFU (Selective Forwarding Unit) for multi-party distribution, and the client-side capture and encoding logic.

The client-side implementation handles capture, encoding, and transmission:

class ScreenShareManager {
  constructor(peerConnection) {
    this.pc = peerConnection;
    this.encoder = new VideoEncoder();
  }
  
  async startCapture() {
    const stream = await navigator.mediaDevices.getDisplayMedia({
      video: { width: 1920, height: 1080 },
      audio: false
    });
    
    const track = stream.getVideoTracks()[0];
    const processor = new MediaStreamTrackProcessor({ track });
    const generator = new MediaStreamTrackGenerator({ kind: 'video' });
    
    // Process and encode frames
    const transformer = new TransformStream({
      transform(videoFrame, controller) {
        // Encode and send via WebRTC
        this.encodeFrame(videoFrame);
        controller.enqueue(videoFrame);
      }
    });
    
    processor.readable.pipeThrough(transformer).pipeTo(generator.writable);
    
    return new MediaStream([generator]);
  }
}

This approach enables custom processing like automatic content detection, quality adaptation, or watermark insertion.

Choosing the Right Approach

For most developer teams, integrating an established service like Daily.co or LiveKit provides the best balance of implementation speed and reliability. Build custom solutions when you need features unavailable through third-party APIs or when infrastructure costs make sense for your scale.

The key factors in your decision are: team size (affects SFU requirements), latency sensitivity (real-time collaboration needs WebRTC), custom processing needs (recording, transcription, content moderation), and browser compatibility requirements.

Start with browser-based capture for the simplest implementation, migrate to WebRTC-based solutions when you need better latency, and consider third-party APIs when building comprehensive meeting platforms. Each approach has a place depending on your specific requirements and engineering resources.

Built by theluckystrike — More at zovo.one