Screen sharing on macOS

Updated at:
Copy as MD

Implement screen sharing on macOS using the ARTC SDK.

Overview

Screen sharing lets users in a channel view your screen in real time during a video call or live stream.

Prerequisites

Before you start:

Usage notes

  • In ARTC versions earlier than 7.6, join a channel before starting screen sharing. Implement audio and video calls.

  • In ARTC 7.6 and later, screen sharing works without joining a channel. Set AliEngineScreenShareConfig.isPushStream to FALSE. After joining the channel, set it to TRUE and call updateScreenShareConfig to start stream ingest.

Implementation

1. Configure screen sharing encoding parameters

Call setScreenShareEncoderConfiguration to configure the screen sharing stream encoding: resolution, frame rate, bitrate, GOP, and rotation.

Note
  • Call this method before or after joining a channel. To set encoding properties once per session, call it before joining.

  • You can call this method multiple times to update the configuration.

Encoding parameters:

Parameter

Description

Default value

dimensions

Video resolution.

0 × 0 (matches the captured screen resolution). Maximum: 3840 × 2160.

frameRate

Video frame rate.

5. Maximum: 30.

bitrate

Video encoding bitrate (Kbps).

The bitrate must match the resolution and frame rate. Out-of-range values are auto-adjusted by the SDK.

512

keyFrameInterval

Keyframe interval (GOP). Unit: ms.

0 (SDK-controlled).

forceStrictKeyFrameInterval

Whether the encoder strictly follows the configured keyframe interval.

false.

  • false: The encoder responds to keyframe requests (e.g., when a new user joins), so the actual interval may differ.

  • true: The encoder ignores external keyframe requests and strictly follows the configured interval. May delay first-frame rendering for subscribers.

rotationMode

Video stream rotation.

AliEngineRotationMode_0. Valid values: 0, 90, 180, 270.

Sample code:

/*
  config is a user-defined configuration struct
*/

AliRtcScreenShareEncoderConfiguration * encoderConfig = [[AliRtcScreenShareEncoderConfiguration alloc] init];

encoderConfig.dimensions = CGSizeMake( width_, height_);
encoderConfig.frameRate = frameRate_;   // 5/10/15...
encoderConfig.bitrate = bitrate_;	// 1200...
encoderConfig.rotation = AliRtcRotationMode_0; // 0/90/180/270
encoderConfig.keyFrameInterval = keyFrameInterval_; // 1/2/3 seconds

if (keyFrameInterval_ > 0) {
    encoderConfig.forceStrictKeyFrameInterval = TRUE;
}

encoderConfig.forceStrictKeyFrameInterval = forceStrictKeyFrameInterval_;

[self.mainEngine setScreenShareEncoderConfiguration: encoderConfig];

2. Set up screen sharing preview

Call setLocalViewConfig to set the display view for the screen sharing stream (AliEngineVideoTrackScreen).

AliVideoCanvas *canvas = [[AliVideoCanvas alloc]init];
canvas.mirrorMode = _mirrorButton.state == NSControlStateValueOn ? AliRtcRenderMirrorModeAllEnabled:AliRtcRenderMirrorModeAllDisabled;
canvas.view = renderView;
int rv = [self.mainEngine setLocalViewConfig:canvas forTrack:AliRtcVideoTrackScreen];

3. View remote screen sharing

Call setRemoteViewConfig in the onRemoteTrackAvailableNotify callback to set the display view for a remote user's screen share.

- (void)onRemoteTrackAvailableNotify:(NSString *)uid audioTrack:(AliRtcAudioTrack)audioTrack videoTrack:(AliRtcVideoTrack)videoTrack {
    
    /* Handle UI components on the main thread */
    
    dispatch_async(dispatch_get_main_queue(), ^{
      AliVideoCanvas *canvas = [[AliVideoCanvas alloc]init];
      if ( videoTrack == AliRtcVideoTrackScreen ) {
          canvas.view = self._screenshareView;
          int rv = [self.mainEngine setLocalViewConfig:canvas forTrack:AliRtcVideoTrackScreen]; 
      } else {
          /* Find the view corresponding to this user */
          canvas.view = self.findView(uid);
          int rv = [self.mainEngine setLocalViewConfig:canvas forTrack:AliRtcVideoTrackScreen]; 
      }

    });

}

4. Enumerate all shareable desktops

Call getScreenShareSourceInfoWithType to get a list of shareable windows and desktops.

A system permission prompt appears. If denied, all subsequent sharing attempts fail.

_screenInfoArray = [self.engine getScreenShareSourceInfoWithType:AliRtcScreenShareDesktop];

/* Add to list */
if (_screenInfoArray) {
    
    for (AliRtcScreenSourceInfo *info in _screenInfoArray) {
        // Name + ID
        NSString *showString = [NSString stringWithFormat:@"%@+%@",info.sourceName,info.sourceId];
        [_screenListBox addItemWithObjectValue:showString];
    }
    
}

5. Start screen sharing

Call startScreenShareWithDesktopId to start screen sharing.

Configure config.isPushStream before starting.

AliRtcScreenShareConfig *config = [[AliRtcScreenShareConfig alloc]init];

/* For region-based sharing */
if ( shareRegion ) {
    
    config.isShareByRegion = TRUE ;
    AliRtcScreenShareRegion *region = [[AliRtcScreenShareRegion alloc]init];
    region.originX = regionRect.origin.x;
    region.originY = regionRect.origin.y;
    region.width = regionRect.size.width;
    region.height = regionRect.size.height;
    
    config.shareRegion = region;
    
} else {
    config.isShareByRegion = FALSE;
}

/* Set to true to push stream immediately; otherwise, set to FALSE
   and call updateScreenShareConfig later */

if ( pushStream ) {
    config.isPushStream = TRUE ;
} else {
    config.isPushStream = FALSE ;
}

/* Set desktop ID from _screenListBox */
int idValue =  [[_screenInfoArray[_screenListBox.indexOfSelectedItem] sourceId] intValue] ;
int r = [self.engine startScreenShareWithDesktopId:idValue config:config];

NSLog(@"startScreenShareWithDesktopId:%d",r);
if ( r != 0 ) {
    // Error handling
} 

6. (Optional) Update configuration

Call updateScreenShareConfig to update the screen sharing configuration.

AliRtcScreenShareConfig *config = [[AliRtcScreenShareConfig alloc]init];

/* For region-based sharing */
if ( share_region ) {
    
    config.isShareByRegion = TRUE ;
    AliRtcScreenShareRegion *region = [[AliRtcScreenShareRegion alloc]init];
    region.originX = regionRect.origin.x;
    region.originY = regionRect.origin.y;
    region.width = regionRect.size.width;
    region.height = regionRect.size.height;
    
    config.shareRegion = region;
    
} else {
    config.isShareByRegion = FALSE;
}

/* Set to true to push stream immediately; otherwise, set to FALSE
   and call updateScreenShareConfig later */

if ( pushStream ) {
    config.isPushStream = TRUE ;
} else {
    config.isPushStream = FALSE ;
}
      
[self.engine updateScreenShareConfig:mScreenConfig];

7. Stop screen sharing

[self.engine stopScreenShare];

Multi-window sharing

Preview, display, and stream ingestion follow the same logic as desktop sharing.

1. List all shareable windows

Call startScreenShareWithWindowId to share a specific window.

_windowInfoArray = [self.engine getScreenShareSourceInfoWithType:AliRtcScreenShareWindow];


/* Display in listBox */
if (_windowInfoArray) {
    for (AliRtcScreenSourceInfo *info in _windowInfoArray) {
        // Name + ID
        NSString *showString = [NSString stringWithFormat:@"%@+%@",info.sourceName,info.sourceId];
        [_windowsListBox addItemWithObjectValue:showString];
    }
}

2. Share a specific window

AliRtcScreenShareConfig *config = [[AliRtcScreenShareConfig alloc]init];

/* For region-based sharing */
if ( shareRegion ) {
    
    config.isShareByRegion = TRUE ;
    AliRtcScreenShareRegion *region = [[AliRtcScreenShareRegion alloc]init];
    region.originX = regionRect.origin.x;
    region.originY = regionRect.origin.y;
    region.width = regionRect.size.width;
    region.height = regionRect.size.height;
    
    config.shareRegion = region;
    
} else {
    config.isShareByRegion = FALSE;
}


/* Set to true to push stream immediately; otherwise, set to FALSE.
   Later, call updateScreenShareConfig to modify the push stream flag */

if ( pushStream ) {
    config.isPushStream = TRUE ;
} else {
    config.isPushStream = FALSE ;
}

/* Set window ID from _windowsListBox */

int idValue =  [[_windowInfoArray[_windowsListBox.indexOfSelectedItem] sourceId] intValue] ;
int r = [self.engine startScreenShareWithWindowId:idValue config:config];

NSLog(@"startScreenShareWithWindowId:%d",r);
if ( r != 0 ) {
    // Error handling
} 

3. Stop sharing a window or desktop

Call stopScreenShare to stop sharing.

[self.mainEngine stopScreenShare];