Suggestions

close search

Add Messaging, Voice, and Authentication to your apps with Vonage Communications APIs

Visit the Vonage API Developer Portal

Screen sharing — Web

You can publish a stream that uses a video view of your screen (instead of a camera) as the source.

A client connected to the session can subscribe to a screen-sharing stream (and view it), just as they would subscribe to a stream that uses a camera as the source. (No browser extension is required to subscribe to a screen-sharing stream.)

Important: As of Chrome 72+, Firefox 52+, and Opera 59+, an extension is no longer needed for screen sharing. The browser prompts the end user for access to the screen as it would for access to the camera.

In older versions of Opera and Chrome, to publish a screen-sharing video, the client needs to add an extension that enables publishing screen-sharing streams for your domain. (See Developing a screen-sharing extension.)

Note: On macOS 10.15+ (Catalina), to publish a screen-sharing stream the user must grant the browser access to the screen in macOS System Preferences > Security & Privacy > Privacy > Screen Recording. Otherwise, the Publisher will dispatch an accessDenied event.

In Electron, screen sharing is supported if the webPreferences.contextIsolation option of the Electron BrowserWindow is set to false or if the app uses a preload script to access the desktop capturer. For details, see Enabling screen-sharing in Electron.

Publishing screen-sharing streams is currently not supported in Safari on iOS or in Safari 12 and older on macOS.

In all supported browsers, publishing a screen-sharing stream requires the page to be loaded over HTTPS.

This topic includes the following sections:

Quick Start

Publishing screen-sharing videos is supported in Chrome, Firefox, Opera, Chromium-based versions of Edge (versions 79+), and Safari 13+. It is currently not supported in mobile browsers, Safari 12 and older on macOS. Publishing a screen-sharing stream is only supported when the web page is loaded via HTTPS.

Note: To support screen-sharing in older versions of Chrome and Opera, you must create a screen-sharing extension. See the following GitHub repository: https://github.com/opentok/screensharing-extensions.

No extension is required to subscribe to a screen-sharing video stream, which is possible in all browsers that support OpenTok.

Developing a screen-sharing extension (deprecated)

Important: Screen sharing extensions are not required in the latest versions of Chrome, Firefox, and Opera.

To support screen-sharing in older versions of Chrome and Opera, you must create a screen-sharing extension. See the following GitHub repository for sample code for screen-sharing extensions:

https://github.com/opentok/screensharing-extensions

Checking for screen-sharing support

To check if publishing a screen-sharing stream is supported in the client browser, call the OT.checkScreenSharingCapability() method. This method takes one parameter: a callback function. The callback function is passed a response object. This object has the following properties that indicate support for publishing screen-sharing streams in the client:

The options parameter also includes the following properties, which apply to screen-sharing support in older versions of Chrome and Opera, which require screen-sharing extensions — in other browsers, they are undefined:

Note: Screen sharing is only supported when the web page is loaded via HTTPS.

The following example shows how to check for screen-sharing support:

OT.checkScreenSharingCapability(function(response) {
  if(!response.supported || response.extensionRegistered === false) {
    // This browser does not support screen sharing
  }
});

Publishing a stream with a screen-sharing source

The videoSource property of the options parameter of the OT.initPublisher() method defines the video source for the stream to be published. For screen-sharing, set this property to "screen". In older browser versions, you could also pass in "application" or "window" to specify a type of screen-sharing source. However, in current browsers that support screen sharing, passing in any of these values results in the same behavior — the browser displays a dialog box in which the end user selects the screen-sharing source (which can be the entire screen or a specific window). In Electron, screen sharing captures the entire screen, without prompting the user for permission. In Safari, initializing a screen-sharing publisher without a user gesture handler may throw an InvalidAccessError error.

The following code shows how to publish a stream that uses screen sharing as the source:

<div id="publisher"></div>
<div id="screen-preview"></div>

OT.checkScreenSharingCapability(function(response) {
  if(!response.supported || response.extensionRegistered === false) {
    // This browser does not support screen sharing.
  } else if (response.extensionInstalled === false) {
    // Prompt to install the extension.
  } else {
    // Screen sharing is available. Publish the screen.
    var publisher = OT.initPublisher('screen-preview',
      {videoSource: 'screen'},
      function(error) {
        if (error) {
          // Look at error.message to see what went wrong.
        } else {
          session.publish(publisher, function(error) {
            if (error) {
              // Look error.message to see what went wrong.
            }
          });
        }
      }
    );
  }
});

Upon error, the completion handler for the OT.initPublisher() method can be passed an error object with one of the following error codes:

When you publish screen-sharing stream, the following default values are set for the options parameter of the OT.initPublisher() method:

Additionally, subscribers to the resulting stream also default to using the "contain" fitMode setting.

For information on maxResolution and fitMode, see the next two sections.

By default, scalable video is disabled for screen-sharing streams. You can enable scalable video for screen-sharing streams by setting the scalableScreenshare option for the OT.initPublisher() method. Note: scalable video for screen-sharing streams is a beta feature.

Setting the maximum resolution of the stream

You can set a maxResolution property when you call the OT.initPublisher() method. This property sets the maximum resolution to stream. When sharing a window, the resolution of the stream will match the window's dimensions unless the window is larger than the maxResolution setting (when the user resizes the window).

The maxResolution property is an object with two properties: width and height. The maximum value for each is 1920, and the minimum value is 10.

var publishOptions = {};
publishOptions.maxResolution = { width: 1920, height: 1080 };
publishOptions.videoSource = 'screen';
OT.initPublisher('some-element-id', publishOptions);

For screen-sharing, do not set the resolution option for the OT.initPublisher() method.

You may not want to display the screen-sharing video in the HTML DOM on the page that you publish it from. For example, if you are sharing the entire screen and you include the video in the HTML DOM, you will see a recursive "hall of mirrors" effect. To prevent this, create an HTML DOM element for the publisher element and do not display the element in the HTML DOM:

var publishOptions = {videoSource: 'screen'};
var screenPublisherElement = document.createElement('div');
OT.initPublisher(screenPublisherElement, publishOptions);

Cropping or letter-boxing screen-sharing videos

You can set a fitMode property of the options parameter you pass into the OT.initPublisher() and Session.subscribe() methods. The fitMode property determines how the video is displayed if the its dimensions do not match those of the DOM element. You can set this property to one of the following values:

Determining the video type ("screen" or "camera") for a stream

The Stream object contains a videoType property. This can be set to one of the following values

This property can change if a stream published from a mobile device changes from a camera to a screen-sharing video type. When the video type changes, the Session object dispatches a streamPropertyChanged event.

The following code subscribes to streams and adds them to different HTML DIV container elements, based on the video type:

<div id="people"></div>
<div id="screens"></div>

session.on('streamCreated', function(event) {
  var subOptions = {insertMode: 'append'};
  if(event.stream.videoType === 'screen') {
    session.subscribe(event.stream, 'screens', subOptions);
  } else {
    session.subscribe(event.stream, 'people', subOptions);
  }
});

Detecting when video dimensions change

The Publisher object that is publishing a screen-sharing stream and a Subscriber object that is subscribing to a screen-sharing stream can each dispatch a videoDimensionsChanged event. The event is dispatched when the publishing client resizes a window being shared.

The videoDimensionsChanged event has the following properties:

You may use the newValue.width and newValue.height properties to adjust the size of the publisher in the HTML DOM:

var publisher = OT.initPublisher('some-element',
  {videoSource: 'screen'});

publisher.on('videoDimensionsChanged', function(event) {
  publisher.element.style.width = event.newValue.width + 'px';
  publisher.element.style.height = event.newValue.height + 'px';
});

Determining when the user stops sharing the screen

When the user stops sharing the screen, the Publisher object dispatches a mediaStopped event.

If the Publisher was also publishing the stream to a session, it also dispatches a streamDestroyed event with the reason property set to "mediaStopped". Also, the Session object on all clients connected to the session dispatches a streamDestroyed event with the reason property set to "mediaStopped".

The default behavior for both the mediaStopped event and the streamDestroyed event is to delete the publisher (or the subscriber in the case of a subscribed stream). Call the preventDefault() method of the event object to prevent the publisher or subscriber from being deleted.

publisher.on('mediaStopped', function(event) {
  // The user clicked stop.
});

publisher.on('streamDestroyed', function(event) {
  if (event.reason === 'mediaStopped') {
    // User clicked stop sharing
  } else if (event.reason === 'forceUnpublished') {
    // A moderator forced the user to stop sharing.
  }
});

Subscribing to screen-sharing streams

You can subscribe to a stream that uses a screen-sharing video source in the same way that you subscribe to a stream that uses a camera as the source. See Subscribing to streams.

You can detect that a stream is a screen-sharing stream, by checking the videoType property of the Stream object. For a screen-sharing stream, this property is set to "screen".

The following code subscribes to streams, appending them to different HTML DOM container elements, based on the video type ("screen" or "camera"):

session.on('streamCreated', function(event) {
  var subOptions = {
    appendMode: 'append'
  };

  var parentElementId = event.stream.videoType === 'screen' ?
    'sub-screen-sharing-container' :
    'sub-camera-container';
  subscriber = session.subscribe(event.stream, parentElement, subOptions);
});

The dimensions of a screen-sharing stream can change if user publishing the stream resizes the window that is the source for the stream. When the video dimensions change, the Subscriber object dispatches a videoDimensionsChanged event.

The following code resizes a subscriber when the stream's video dimensions change:

subscriber.on('videoDimensionsChanged', function(event) {
  subscriber.element.style.width = event.newValue.width + 'px';
  subscriber.element.style.height = event.newValue.height + 'px';
  // You may want to adjust other UI.
});

Enabling screen sharing in Electron

In Electron, screen sharing is supported if the webPreferences.contextIsolation option of the Electron BrowserWindow is set to false or if the app uses a preload script to access the desktop capturer. The default value of webPreferences.contextIsolation option is true in Electron 12+ and false in previous versions. In Electron 17+, a breaking change was introduced, causing screen sharing to only be available after using a preload script.

Enabling screen sharing via preload script in Electron versions 12-16

To enable screen sharing in Electron versions 12-16 using a preload script, add the following to the preload.js file:

const {
  contextBridge,
  desktopCapturer
} = require('electron');
// Expose the desktopCapturer so that OpenTok.js can access it
// via window.electron.desktopCapturer
contextBridge.exposeInMainWorld(
  'electron', {
    desktopCapturer,
  }
);

Then reference preload.js when instantiating a BrowserWindow in Electron:

mainWindow = new BrowserWindow({
  webPreferences: {
    nodeIntegration: true,
    preload: path.join(__dirname, 'preload.js'), // use the preload script
  }
});

Enabling screen sharing via preload script in Electron versions 17+

To enable screen sharing in Electron versions 17+, add the following to the preload.js file:


const {
  contextBridge,
  ipcRenderer
} = require('electron');

// Event emitter to send asynchronous messages to the main process. The
// corresponding ipcMain handler listens for the 'DESKTOP_CAPTURER_GET_SOURCES'
// channel and returns an array of the available DesktopCapturerSource objects.
const desktopCapturer = {
  getSources: (opts) => ipcRenderer.invoke('DESKTOP_CAPTURER_GET_SOURCES', opts)
};

// Expose desktopCapturer so that the SDK can access it.
contextBridge.exposeInMainWorld(
  'electron', {
    desktopCapturer
  }
);

Then reference preload.js when instantiating a BrowserWindow in Electron:


// Event emitter to handle messages sent from the renderer process. This handler
// will be called whenever a renderer calls
// ipcRenderer.invoke('DESKTOP_CAPTURER_GET_SOURCES', ...args)
electron.ipcMain.handle(
  'DESKTOP_CAPTURER_GET_SOURCES',
  (event, opts) => electron.desktopCapturer.getSources(opts)
);

mainWindow = new BrowserWindow({
  webPreferences: {
    preload: path.join(__dirname, 'preload.js') // use a preload script
  }
});

Optimizing video perfomance of certain screen-sharing streams

You can set a video content hint to improve the quality and performance of a screen-sharing video that will primarily contain either text or video content. For details, see Setting video content hints to improve video perfomance in certain situations.