Screen sharing on macOS
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:
-
An Alibaba Cloud account with an ARTC application created. Create an application. Get the App ID and App Key from the console.
-
The ARTC SDK integrated into your project with basic audio and video features implemented. SDK download and integration. Implement audio and video calls.
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.isPushStreamto FALSE. After joining the channel, set it to TRUE and callupdateScreenShareConfigto 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.
-
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.
|
|
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];