# 屏幕共享 (/zh-CN/realtime-media/rtc/build/video/screen-share/macos)

> For AI agents: see the complete documentation index at [llms.txt](/llms.txt).

在互动直播或视频通话中，主播或视频通话用户可以通过声网 SDK 中的屏幕共享特性，将自己的屏幕内容以视频的方式分享给其他用户或观众观看。

屏幕共享可以应用在以下场景中：

| 场景     | 描述                                                         |
| :------- | :----------------------------------------------------------- |
| 在线教育 | 老师将自己的屏幕、教学课件、绘图软件或编程软件共享给学生，用于课堂示范 |
| 游戏直播 | 主播共享自己的游戏画面给观众                                 |
| 互动直播 | 主播共享自己的屏幕和观众互动                                 |
| 视频会议 | 会议成员共享屏幕观看 PPT 或者文档                            |
| 远程控制 | 被控端向主控端展示自己的桌面                                 |

## 注意事项 [#注意事项-2]

- 在开启屏幕共享后，声网以屏幕共享视频流的分辨率作为计费标准。默认分辨率为 1920 x 1080，你也可以根据你的业务需求进行调整。详见[如何确定屏幕共享视频流的分辨率？](/zh-CN/realtime-media/rtc/reference/billing-faq#screencapture)
- 如果要在屏幕共享时共享 4K 分辨率的超高清视频，你的设备需要满足一定要求，声网推荐的最低设备规格为：2021 年 M1 MacBook Pro 16 英寸。
- 在屏幕共享 > 共享窗口 > 最小化窗口场景下，接收端显示的画面会停留在窗口最小化前的最后一帧。由于捕捉屏幕时窗口正处于最小化动画中，在 macOS 26 系统上，该最后一帧有概率发生变形。此时发送端会收到 `localVideoStateChangedOfState` 回调，其中 `reason` 为 `ScreenCaptureWindowMinimized`。你可以通过该回调告知远端用户屏幕共享已进入最小化状态。

## 前提条件 [#前提条件-2]

- 在实现屏幕共享前，请确保已在你的项目中实现基本的实时音视频功能。详见[实现音视频互动](/zh-CN/realtime-media/rtc/get-started/quick-start)。
- 要实现屏幕共享，请确保在集成 SDK 时不要手动删除屏幕共享动态库（`AgoraScreenCaptureExtension.xcframework`），否则会导致该功能无法正常使用。

## 实现屏幕共享 [#实现屏幕共享-2]

本节介绍如何在你的项目中实现屏幕共享，API 调用时序如下图所示。

<DocsImage alt="流程图" src="https://web-cdn.agora.io/docs-portal/img/rtc/screen-share/screen-share-process-pc.svg" displayWidth="70%" />

开启屏幕共享有如下两种方案，你可以根据实际场景进行选择：

- 在加入频道前调用 `startScreenCaptureByDisplayId` 或 `startScreenCaptureByWindowId`，然后调用 `joinChannelByToken` [2/4] 加入频道并设置 `publishScreenTrack` 或 `publishSecondaryScreenTrack` 为 `true`，即可开始屏幕共享。
- 在加入频道后调用该 `startScreenCaptureByDisplayId` 或 `startScreenCaptureByWindowId`，然后调用 `updateChannelWithMediaOptions` 设置 `publishScreenTrack` 或 `publishSecondaryScreenTrack` 为 `true`，即可开始屏幕共享。

本文中的流程图和步骤均以第一种方案为例。

参考如下具体步骤，实现屏幕共享。

### 获取资源列表 [#获取资源列表]

调用 `getScreenCaptureSourcesWithThumbSize`，获取可共享的屏幕和窗口的对象列表，列表中包含窗口 ID 和屏幕 ID 等重要信息，方便用户通过列表中的缩略图选择共享某个显示器的屏幕或某个窗口。示例代码如下：

```swift
// 获取可用的屏幕信息
@IBAction func onScreentThumbnailButton(_ sender: NSButton) {
        let result = agoraKit.getScreenCaptureSources(withThumbSize: NSScreen.main?.frame.size ?? .zero, iconSize: .zero, includeScreen: true)
        saveThumbnailToDesktop(result: result, type: .screen)
    }

// 获取可用的窗口信息
@IBAction func onWindowThumbnailButton(_ sender: NSButton) {
        let result = agoraKit.getScreenCaptureSources(withThumbSize: selectedResolution?.size() ?? .zero, iconSize: .zero, includeScreen: true)
        saveThumbnailToDesktop(result: result, type: .window)
    }
```

### 开启屏幕共享 [#开启屏幕共享]

根据实际应用场景，在以下 3 种屏幕共享方式中任选一种。

#### 共享整个屏幕 [#共享整个屏幕-2]

调用 `startScreenCaptureByDisplayId` 开始共享整个屏幕，参数设置如下：

- 将 `displayId` 设置为上一步获取到的 `sourceId` (屏幕 ID)。
- 在 `captureParams` 中设置你预期的视频编码属性。
  - 在文档场景或远程控制场景下，推荐将 `dimensions` 设置为 1920 × 1080；`frameRate` 设置为 10 fps。
  - 在游戏场景或视频场景下，推荐将 `dimensions` 设置为 960 × 720；`frameRate` 设置为 15 fps。

```swift
// 开始共享指定的屏幕
let result = agoraKit.startScreenCapture(byDisplayId: UInt32(screen.id), regionRect: .zero, captureParams: params)
```

#### 共享 App 窗口 [#共享-app-窗口-2]

调用 `startScreenCaptureByWindowId` 开始共享指定 App 窗口，参数设置如下：

- 将 `windowId` 设置为上一步获取到的 `sourceId`（窗口 ID）。
- 在 `captureParams` 中设置你预期的视频编码属性。
  - 在文档场景或远程控制场景下，推荐将 `dimensions` 设置为 1920 × 1080；`frameRate` 设置为 10 fps。
  - 在游戏场景或视频场景下，推荐将 `dimensions` 设置为 960 × 720；`frameRate` 设置为 15 fps。

```swift
// 开始共享指定的 App 窗口
let result = agoraKit.startScreenCapture(byWindowId: UInt32(window.id), regionRect: .zero, captureParams: params)
```

#### 共享指定区域 [#共享指定区域-2]

调用 `startScreenCaptureByDisplayId` 或 `startScreenCaptureByWindowId` 方法开始共享，并将 `regionRect` 设置为你想要共享的区域相对于整个屏幕或窗口的位置。示例代码如下：

```swift
// 设置你想要共享的区域参数
// 如果设置的共享区域超出了屏幕的边界，则只共享屏幕内的内容；如果宽或高设为 0，则共享整个屏幕
// 下一行代码指定了一个长度和宽度均为 100 px 的矩形，该矩形左上角的 x 坐标和 y 坐标均为 0
let captureRect = CGRect(x: 0, y: 0, width: 100, height: 100)
let result = agoraKit.startScreenCapture(byWindowId: UInt32(window.id), regionRect: captureRect, captureParams: params)
```

### （可选）设置屏幕共享场景 [#可选设置屏幕共享场景-2]

调用 `setScreenCaptureScenario` 方法设置屏幕共享场景，按照实际使用场景，将 `scenarioType` 设置为以下任意一种：

- `AgoraScreenScenarioDocument`(1)：文档场景
- `AgoraScreenScenarioGaming`(2)：游戏场景
- `AgoraScreenScenarioVideo`(3)：视频场景
- `AgoraScreenScenarioRDC`(4)：远程控制场景

示例代码如下：

```swift
agoraKit.setScreenCaptureScenario(.video)
```

### （可选）采集系统音频 [#可选采集系统音频]

如果你想要同时采集并发布共享屏幕或窗口中播放的音频，可以调用 `enableLoopbackRecording` 方法开启声卡采集，系统播放的音频会被合入到本地音频流中。

:::warning[注意]
调用该方法后，系统其他进程播放的音频也会被发布到远端，如果这并非你的预期，请再次调用该方法，关闭声卡采集。
:::

### 加入频道并发布屏幕共享视频流 [#加入频道并发布屏幕共享视频流-1]

调用 `joinChannelByToken` [2/4] 加入频道并设置频道媒体选项。示例代码如下：

```swift
// 设置频道场景
agoraKit.setChannelProfile(.liveBroadcasting)
// 设置用户角色
agoraKit.setClientRole(.broadcaster)
// 设置频道媒体选项
// 在频道中发布屏幕采集的视频
// 如果要在频道中发布第二个屏幕采集的视频，则将下一行代码替换为 mediaOptions.publishSecondaryScreenTrack = true
mediaOptions.publishScreenTrack = true
// 加入频道
let result = self.agoraKit.joinChannel(byToken: token, channelId: channel, uid: 0, mediaOptions: option)
```

:::info[信息]
本文以直接在频道中发布屏幕共享流、不发布摄像头采集的流为例，实际应用场景中的发流方式可能跟本文的描述不同，请结合实际应用场景调整你的代码逻辑。如果你需要同时发布摄像头采集的流和屏幕共享流，可参考以下步骤：

1. 调用 `joinChannelByToken` [2/4] 加入第一个频道，在该频道中发布摄像头采集的视频流。
1. 调用 `joinChannelEx` 加入第二个频道，在该频道中发布屏幕共享流。
:::

### （可选）更新屏幕共享区域或参数 [#可选更新屏幕共享区域或参数]

在频道中，你可以调用如下方法动态更新屏幕共享区域或参数：

- 如果你要更新屏幕共享的区域，调用 `updateScreenCaptureRegion` 方法，重新设置 `regionRect` 参数、划定新的共享区域。

- 如果你要更新屏幕共享的参数（例如：视频编码分辨率、帧率、码率；对屏幕或 App 窗口描边；是否屏蔽指定窗口等），调用 `updateScreenCaptureParameters` 方法，更新 `captureParams` 参数的配置。

示例代码如下：

```swift
// 更新屏幕共享区域
let rect = NSScreen.main?.frame
let region = NSMakeRect(0, 0, !toggleRegionalScreening ? rect!.width / 2 : rect!.width, !toggleRegionalScreening ? rect!.height / 2 : rect!.height)
agoraKit.updateScreenCaptureRegion(region)

// 设置新的屏幕采集参数
private lazy var screenParams: AgoraScreenCaptureParameters2 = {
    let params = AgoraScreenCaptureParameters2()
    params.captureVideo = true
    params.captureAudio = true
    let audioParams = AgoraScreenAudioParameters()
    // 设置采集的系统音量
    audioParams.captureSignalVolume = 70 // 更新音量
    params.audioParams = audioParams
    let videoParams = AgoraScreenVideoParameters()
    // 更新共享屏幕的分辨率
    videoParams.dimensions = CGSizeMake(1280, 960) // 更新为 1280 x 960
    // 更新视频编码帧率
    videoParams.frameRate = .fps30 // 更新为 30 fps
    // 更新视频编码码率
    videoParams.bitrate = 1500 // 更新为 1500 Kbps
    params.videoParams = videoParams
    return params
}()

// 更新屏幕共享参数
agoraKit.updateScreenCaptureParameters(captureParams)
```

### （可选）对屏幕描边 [#可选对屏幕描边]

根据实际使用场景，你可以通过以下两种方式对屏幕或窗口进行描边。

- 在开启屏幕共享时描边：调用 `startScreenCaptureByDisplayId` 或 `startScreenCaptureByWindowId`，将 `captureParams` 中的 `highLighted` 设置为 `true`，并同时设置 `highLightColor` 和 `highLightWidth` 来指定描边的颜色和宽度。
- 在开启屏幕共享后描边：调用 `updateScreenCaptureParameters`，将 `captureParams` 中的 `highLighted` 设置为 `true`，并同时设置 `highLightColor` 和 `highLightWidth` 来指定描边的颜色和宽度。

```swift
let params = AgoraScreenCaptureParameters()
params.frameRate = fps
params.dimensions = resolution.size()
// 设置屏幕的描边宽度
params.highLightWidth = 5
// 设置屏幕的描边颜色
params.highLightColor = .green
// 开启屏幕描边
params.highLighted = true
let result = agoraKit.startScreenCapture(byDisplayId: UInt32(screen.id), regionRect: .zero, captureParams: params)
```

### （可选）屏蔽窗口 [#可选屏蔽窗口]

根据实际使用场景，你可以通过以下两种方式屏蔽指定的窗口。

- 在开启屏幕共享时屏蔽窗口：调用 `startScreenCaptureByDisplayId`，将 `captureParams` 中的 `excludeWindowList` 设置为你想要屏蔽的窗口列表。
- 在开启屏幕共享后屏蔽窗口：调用 `updateScreenCaptureParameters`，将 `captureParams` 中的 `excludeWindowList` 设置为你想要屏蔽的窗口列表。

```swift
let captureParams = AgoraScreenCaptureParameters()
captureParams.excludeWindowList = windowlist.filter({ $0.id != window.id })
agoraKit.updateScreenCaptureParameters(captureParams)
```

### 停止屏幕共享 [#停止屏幕共享-2]

调用 `stopScreenCapture`，在频道内停止屏幕共享。示例代码如下：

```swift
// 停止屏幕共享
agoraKit.stopScreenCapture()
```

## 参考信息 [#参考信息-2]

### 功能介绍 [#功能介绍-2]

声网 SDK 的屏幕共享特性可提供以下功能，适用于各种场景下的屏幕共享。

![](https://web-cdn.agora.io/docs-files/1680251438368)

:::info[信息]
屏幕共享功能在各平台的适用情况如下：

- 桌面端（Windows 和 macOS）：支持上述所有屏幕共享功能。
- 移动端（Android 和 iOS）：仅支持共享整个屏幕。
:::

#### 共享整个屏幕 [#共享整个屏幕-3]

将你的整个屏幕进行共享，包括屏幕中的所有信息，该功能支持同时采集两块屏幕的信息并共享。

#### 共享 App 窗口 [#共享-app-窗口-3]

如果你不希望将整个屏幕内容分享给其他用户，可以只共享一个 App 窗口中的画面。

#### 共享指定区域 [#共享指定区域-3]

如果你只希望共享屏幕或 App 窗口中的一部分，可以在开启屏幕共享时设置一个共享区域，只有该区域内的画面会被分享。

#### 高级功能 [#高级功能-2]

除上述功能外，你还可以在开启屏幕共享时通过调整参数，实现以下高级共享功能：

- 屏蔽指定 App 窗口：在共享屏幕时，如果你不希望暴露某个 App 窗口，可以选择将该 App 窗口屏蔽，则该窗口将不会出现在共享的屏幕中。
- 描边：如果你需要勾勒出正在共享的范围，可以对指定的 App 窗口或屏幕进行描边，并自定义描边的宽度、颜色和透明度。
- 前置指定 App 窗口：如果你同时共享了多个 App 窗口，可能会出现窗口之间互相遮挡的情况，你可以指定一个 App 窗口并将其前置，即可避免它被其他窗口遮挡。
- 设置共享场景：SDK 会根据你设置的场景自动调节 QOE (Quality of Experience) 策略。
  - 在共享文档、幻灯片、表格，或者远程控制时，你可以将共享场景设置为文档场景或远程控制场景，SDK 会优先保障画质，并降低接收端看共享视频的延时。
  - 在共享游戏或电影、视频直播时，你可以将共享场景设置为游戏场景或视频场景，SDK 会优先保障流畅性。

### 优势介绍 [#优势介绍-2]

声网提供的屏幕共享特性具备以下优势：

**超高清画质体验**

支持分辨率为 4K、帧率为 60 fps 的超高清视频。

**多 App 支持**

适配 WPS Office、Microsoft PowerPoint、Visual Studio Code、Adobe Photoshop、Windows Media Player 和 Scratch 等多款主流 App，方便用户在屏幕共享时直接共享指定 App，提升功能易用性。

**多设备支持**

支持多设备同时共享，兼容 Windows 8 系统、无独立显卡的设备、双显卡设备、外接屏幕设备等，满足各种场景下的设备使用需求。

**多平台适配**

支持 iOS、Android、macOS、Windows、Web、Unity、Flutter、React Native、Unreal Engine 等平台。

**高安全保障**

支持仅共享 App 和屏幕中的部分区域内容，并支持屏蔽指定 App 窗口，有效保障用户信息安全。

### 示例项目 [#示例项目-2]

声网提供了开源的示例项目供你参考，你可以前往下载或查看其中的源代码。

<Cards>
  <Card title={<RepositoryCardTitle provider="gitee">ScreenShare</RepositoryCardTitle>} href="https://gitee.com/agoraio-community/API-Examples/tree/main/macOS/APIExample/Examples/Advanced/ScreenShare" />
  <Card title={<RepositoryCardTitle provider="github">ScreenShare</RepositoryCardTitle>} href="https://github.com/Shengwang-Community/API-Examples/blob/main/macOS/APIExample/Examples/Advanced/ScreenShare" />
</Cards>

### API 参考 [#api-参考-2]

- [`getScreenCaptureSourcesWithThumbSize`](/zh-CN/api-reference/rtc/macos/video/screencapture#api_irtcengine_getscreencapturesources)
- [`startScreenCaptureByDisplayId`](/zh-CN/api-reference/rtc/macos/video/screencapture#api_irtcengine_startscreencapturebydisplayid)
- [`startScreenCaptureByWindowId`](/zh-CN/api-reference/rtc/macos/video/screencapture#api_irtcengine_startscreencapturebywindowid)
- [`setScreenCaptureScenario`](/zh-CN/api-reference/rtc/macos/video/screencapture#setscreencapturescenario)
- [`updateScreenCaptureParameters`](/zh-CN/api-reference/rtc/macos/video/screencapture#updatescreencaptureparameters)
- [`updateScreenCaptureRegion`](/zh-CN/api-reference/rtc/macos/video/screencapture#updatescreencaptureregion)
- [`stopScreenCapture`[1/2]](/zh-CN/api-reference/rtc/macos/video/screencapture#api_irtcengine_stopscreencapture)


















