Tutorial: Screen Sharing

Screen Sharing

WebRTC screen sharing is supported on Chrome M72+ and Safari 13.

The process of using WebRTC to share the screen is the same as that of creating and publishing a local stream, except that different parameters are passed in to TRTC.createStream.

You can use the TRTC.isScreenShareSupported API provided by WebRTC to check whether your browser supports screen sharing.

I. Creating and Publishing Screen Sharing Stream

It’s important that you execute the code for creating and publishing the screen sharing stream in the order specified below.

Step 1. Create a screen sharing client

const shareClient = TRTC.createClient({
  mode: 'rtc',
  sdkAppId,
  userId,
  userSig
});

Step 2. Create a screen sharing stream

// Capture the screen sharing stream only
const shareStream = TRTC.createStream({ audio: false, screen: true, userId });
// Capture audio from the mic and the screen sharing stream
// const shareStream = TRTC.createStream({ audio: true, screen: true });
// Capture system audio and the screen sharing stream
// const shareStream = TRTC.createStream({ screenAudio: true, screen: true });
// You cannot set both audio and screenAudio to true. Find more information about screenAudio in the 5th part of this document.

Step 3. Initialize the screen sharing stream

Initialize the screen sharing stream. The browser will ask the user’s permission to share the screen. If the user denies the permission or cancels screen sharing, or the system does not grant the permission, the NotReadableError or NotAllowedError error will be returned.

try {
  await shareStream.initialize();
} catch (e) {
  // If the initialization of the screen sharing stream fails, notify the user and stop performing subsequent steps including room entry and stream publishing.
  switch (e.name) {
    case 'NotReadableError':
      // Ask the user to check if the system has allowed the browser to record the screen
      return;
    case 'NotAllowedError':
      if (e.message === 'Permission denied by system') {
        // Ask the user to check if the system has allowed the browser to record the screen
      } else {
        // The user denied the permission or canceled screen sharing.
      }
      return;
    default:
      // An unknown error occurred during the initialization of the screen sharing stream. Ask the user to try again.
      return;
  }
}

Step 4. Enter a room

try {
  await shareClient.join({ roomId });
  // ShareClient join room success
} catch (e) {
  // ShareClient join room failed
}

Step 5. Publish the screen sharing stream

try {
  await shareClient.publish(shareStream);
} catch (e) {
  // ShareClient failed to publish local stream
}

Once the above steps are completed, you will be able to share the screen with WebRTC.


II. Screen Sharing Properties

Screen sharing properties include resolution, frame rate, and bitrate. You can use the setScreenProfile() API to specify a screen sharing profile. Each profile corresponds to a set of resolution, frame rate, and bitrate.

const shareStream = TRTC.createStream({ userId, audio: false, screen: true });
shareStream.setScreenProfile('1080p');
await shareStream.initialize();

You can also specify a custom value for the resolution, frame rate, and bitrate.

const shareStream = TRTC.createStream({ userId, audio: false, screen: true });
shareStream.setScreenProfile({ width: 1920, height: 1080, frameRate: 5, bitrate: 1600 /* kbps */});
await shareStream.initialize();

Screen sharing profiles:

Profile Resolution (W × H) Frame Rate (fps) Bitrate (Kbps)
480p 640 × 480 5 900
480p_2 640 × 480 30 1000
720p 1280 × 720 5 1200
720p_2 1280 × 720 30 3000
1080p 1920 × 1080 5 1600
1080p_2 1920 × 1080 30 4000
  • 1080p is the default profile for screen sharing.

III. Stopping Screen Sharing

// The screen sharing client stops publishing.
await shareClient.unpublish(shareStream);
// Close the screen sharing stream
shareStream.close();
// The screen sharing client leaves the room.
await shareClient.leave();
// The three steps above are optional. You can use the code based on your needs. You will probably need to add code to determine whether the client is in the room and whether the stream is being published. For details, please refer to the official demo.

A user may also stop screen sharing by clicking the browser’s built-in button, so it’s necessary to listen for the screen sharing stopping event.

// Listen for the screen sharing stopping event
shareStream.on('screen-sharing-stopped', event => {
  // The screen sharing client stops publishing.
  await shareClient.unpublish(shareStream);
  // Close the screen sharing stream
  shareStream.close();
  // The screen sharing client leaves the room.
  await shareClient.leave();
});

VI. Publishing Both Camera and Screen Sharing Streams

Each Client can publish at most 1 audio track and 1 video track at a time. To publish both the camera and screen sharing streams, you are advised to create two clients, one for publishing the local audio/video stream and the other the screen sharing stream.

userId: ID of the user to whom the audio/video stream belongs
client: the client that publishes the audio/video stream

TRTC.createClient({ mode: 'rtc', sdkAppId, userId, userSig });  

localStream: the local audio/video stream

TRTC.createStream({ audio: true, video: true }); 

shareUserId: ID of the screen sharing user

let shareUserId = `share-${userId}`;

shareClient: the screen sharing client

TRTC.createClient({ mode: 'rtc', sdkAppId, userId: shareUserId, userSig });  

shareStream: the screen sharing stream

TRTC.createStream({ audio: false, screen: true });  

Pay attention to the following when you publish both the camera and screen sharing streams:

  1. Make sure that the screen sharing client does not subscribe to remote streams.
// The automatic subscription mode is enabled by default, which means that audio and video data is decoded automatically after the stream-added callback is received.
// As the screen sharing client publishes data but does not receive data, it needs to unsubscribe from the stream received.
shareClient.on('stream-added', event => {
  const remoteStream = event.stream;
  shareClient.unsubscribe(remoteStream);
});
// In v4.8.0 and above, you can disable the automatic subscription mode. You no longer need to call the unsubscribe API after disabling the mode.
// For details, please see: https://web.sdk.qcloud.com/trtc/webrtc/doc/en/TRTC.html#.createClient
  1. Make sure that the audio/video client unsubscribes from the stream of shareUserId.
  client.on('stream-added', event => {
    const remoteStream = event.stream;
    const remoteUserId = remoteStream.getUserId();
    if (remoteUserId === shareId) {
      // Unsubscribe from the screen sharing stream
      client.unsubscribe(remoteStream);
    } else {
      // Subscribe to other remote streams
      client.subscribe(remoteStream);
    }
  });

V. Capturing System Audio During Screen Sharing

System audio capturing is supported on Chrome M74+ only. On Chrome for Windows and Chrome OS, you can capture the audio of the entire system, while on Chrome for Linux and macOS, you can capture only the audio of Chrome tabs. Other Chrome versions, OS, and browsers do not support system audio capturing.

// Set screenAudio to true when creating the screen sharing stream. Don’t set audio to true as you cannot capture audio from the mic and the screen sharing stream at the same time.
const shareStream = TRTC.createStream({ userId, screenAudio: true, screen: true });
...

In the dialog box that pops up, check Share audio, and the stream published will contain system audio.

VI. Notes

  • The TRTC SDK for web does not support publishing substreams, and screen sharing streams are published as primary streams. Therefore, if a remote screen sharing stream is from a browser, the RemoteStream.getType() API will return main.

  • The TRTC SDK for native applications support publishing substreams, and screen sharing streams are published as substreams. Therefore, if a remote screen sharing stream is from a native application, the RemoteStream.getType() API will return auxiliary.

  • Electron uses TRTC Web SDK for screen sharing

  • Get displaySurface form shareStream.

    const shareStream = TRTC.createStream({ screenAudio: true, screen: true, userId });
    await shareStream.initialize();
    const { displaySurface } = shareStream.getVideoTrack().getSettings();