实时音视频
  • iOS : Objective-C
  • Android
  • macOS
  • Windows
  • HarmonyOS
  • Linux
  • Web
  • 小程序
  • Flutter
  • Electron
  • Unity3D
  • uni-app
  • React Native
  • Cocos Creator
  • 产品简介
  • 下载
  • 体验 App
  • 快速开始
    • 跑通示例源码
    • 集成 SDK
    • 实现视频通话
    • 实时音视频 SDK 与实时语音 SDK 差异
    • 场景化音视频配置
  • 基础功能
  • 进阶功能
  • 最佳实践
  • 常见错误码
  • 服务端 API
  • 客户端 API
  • 常见问题

屏幕共享

更新时间:2022-12-14 18:20

1 功能简介

屏幕共享是指在视频通话或互动直播过程中将屏幕内容以视频的方式分享给其他的观众,以增强互动体验,提高沟通效率。

屏幕共享在如下场景中应用广泛:

  • 视频会议场景中,屏幕共享可以将讲话者本地的文件、数据、网页、PPT 等画面分享给其他与会人;
  • 在线课堂场景中,屏幕共享可以将老师的课件、笔记、讲课内容等画面展示给学生观看。

/Pics/Express/screen_share_scene.jpg

2 示例源码下载

请参考 下载示例源码 获取源码。

相关源码请查看 "/ZegoExpressExample/Examples/Others/ScreenSharing" 目录下的文件。

ZegoExpressExample
...
├── Examples
...
│   ├── Others
...
│   │   ├── ScreenSharing
│   │   │   ├── ScreenCapture.storyboard 
│   │   │   ├── ZGScreenCaptureViewController.h
│   │   │   ├── ZGScreenCaptureViewController.m
│   │   │   └── ZegoExpressExample-Broadcast
│   │   │       ├── Info.plist
│   │   │       ├── SampleHandler.h 
│   │   │       ├── SampleHandler.m
│   │   │       └── ZegoExpressExample-Broadcast.entitlements
...

3 前提条件

在实现屏幕共享功能之前,请确保:

  • 支持 iOS 12.0 或以上版本且支持音视频的 iOS 设备或模拟器(推荐使用真机)。
  • 该功能对设备性能要求较高,推荐在 iPhone X 及之后机型上使用。
  • 已在项目中集成 ZEGO Express SDK,实现基本的实时音视频功能,详情请参考 快速开始 - 集成快速开始 - 实现视频通话
  • 已在 ZEGO 控制台 创建项目,并申请有效的 AppID 和 AppSign,详情请参考 控制台 - 项目管理 中的“项目信息”。

4 实现流程

iOS 平台是基于苹果的 Replaykit 框架实现屏幕录制,能够分享整个系统的屏幕内容。但需要当前 App (主 App 进程)额外提供一个 Extension 扩展组件(Extension 进程),用于录制屏幕,再结合 ZEGO Express SDK 相关 API 来实现屏幕共享功能。

实现屏幕共享的主要流程如下:

  1. 切换采集源为屏幕共享源。
  2. 在您的工程中,新建一个 Broadcast Upload Extension 的 Target,并在其中集成 ZEGO Express SDK。
  3. 使用 Extension 进程录制屏幕,通过 ZegoReplayKitExt 类中的对应方法,将录制的屏幕缓存数据发送给 ZEGO Express SDK。
  4. 开始准备屏幕共享。
  5. 启动屏幕共享 Extension 拓展进程。

详细的操作请参考下文。

如果您想自己实现屏幕共享功能,请参考 如何通过自定义采集实现屏幕共享?

5 使用步骤

5.1 在主 App 设置采集源为屏幕共享源

5.1.1 视频源

SDK 推流的视频源默认为摄像头源,如果需要推屏幕共享源,需要通过 setVideoSource 进行切换为屏幕共享。

[ZegoExpressEngine.shareEnigne setVideoSource:ZegoVideoSourceScreenCapture channel:ZegoPublishChannelMain];

5.1.2 音频源

SDK 推流的音频源默认为麦克风源,如果需要推屏幕共享源,需要通过 setAudioSource 进行切换为屏幕共享。

[ZegoExpressEngine.shareEnigne setAudioSource:ZegoAudioSourceTypeScreenCapture channel:ZegoPublishChannelMain];

5.2 应用内屏幕共享

若用户只在应用内共享画面与声音,可以调用 startScreenCaptureInApp 接口开启屏幕共享。

ZegoScreenCaptureConfig *config = [[ZegoScreenCaptureConfig alloc] init];
config.captureVideo = true;
config.captureAudio = true;
[ZegoExpressEngine.sharedEngine startScreenCaptureInApp:config];

5.3 跨应用屏幕共享

若用户需要共享整个系统的画面与声音,可以调用 startScreenCapture 接口开启屏幕共享。

跨应用屏幕共享是由 iOS 系统通过 Extension 扩展进程进行录制的,所以需要再额外创建扩展进程,并启动。

ZegoScreenCaptureConfig *config = [[ZegoScreenCaptureConfig alloc] init];
config.captureVideo = true;
config.captureAudio = true;
[ZegoExpressEngine.sharedEngine startScreenCapture:config];

5.3.1 新建 Broadcast Upload Extension

Broadcast Upload Extension 的内存使用限制为 50 MB,请勿在屏幕共享的 Extension 中进行额外的内存分配。

  1. 使用 Xcode 打开项目工程文件,在菜单栏中依次点击 “File > New > Target..."。
  2. 在弹出的窗口中选择 iOS 页的 “Broadcast Upload Extension” 后,单击 “Next”。
  3. 在弹出的对话框中的 “Product Name” 一栏填写 “Broadcast Upload Extension” 的名字,例如 “ScreenShare”。选择 “Team”、“Language” 等信息后,单击 “Finish” 。

无需勾选 “Include UI Extension”。

创建完成后,您会在项目中看到该 Extension 的文件夹,结构类似如下,该文件夹用于存放屏幕共享功能的实现代码:

5.3.2 通过 Extension 获取屏幕数据并推流

如下系统回调的实现可以在 下载示例源码 中的 “/ZegoExpressExample-iOS-OC/Topics/ScreenCapture/ZegoExpressExample-iOS-OC-Broadcast/SampleHandler.m” 文件中查看:

  1. 确保 Extension 的 “Info.plist” 文件中,将 “RPBroadcastProcessMode” 设置为 “RPBroadcastProcessModeSampleBuffer”。
  2. 在 Extension 中导入 ZEGO Express SDK,详情请参考 快速开始 - 集成 中的 “导入 SDK”。
  3. 系统通过 broadcastStartedWithSetupInfo 回调通知 Extension 已开始录制屏幕,您需要在该回调中,调用 ZegoReplayKit 类中的如下接口创建数据传输通道:
    [ZegoReplayKitExt.sharedInstance setupWithDelegate:self];
  1. processSampleBuffer 系统回调中,通过 ZegoReplayKit 类中的 sendSampleBuffer 接口发送给 ZEGO Express SDK。

    [ZegoReplayKitExt.sharedInstance sendSampleBuffer:sampleBuffer withType:sampleBufferType];
    
  2. 系统通过 broadcastFinished 回调通知 Extension 屏幕录制已结束,您可以在该回调中,调用 ZegoReplayKit 类中的如下接口停止屏幕共享并断开数据传输通道:

    [ZegoReplayKitExt.sharedInstance finished];

5.3.3 启动 Extension 扩展进程

  • 方式一:

您需要在 iOS 系统的控制中心,长按录屏按钮后,选择对应的 Extension 来开启录制。

  • 方式二:

苹果在 iOS 12.0 中新增了 RPSystemBroadcastPickerView,可以从 App 应用弹出启动器,供用户确认启动屏幕分享。

  1. 创建 RPSystemBroadcastPickerView 系统类,绑定 Extension 的 “BundleID”。
  2. 遍历 RPSystemBroadcastPickerView 的子 view 寻找 UIButton, 并触发其点击事件。
RPSystemBroadcastPickerView *broadcastPickerView = [[RPSystemBroadcastPickerView alloc] initWithFrame:CGRectMake(0, 0, 44, 44)];
NSString *bundlePath = [[NSBundle mainBundle] pathForResource:@"ZegoExpressExample-Broadcast" ofType:@"appex" inDirectory:@"PlugIns"];
if (bundlePath) {
    NSBundle *bundle = [NSBundle bundleWithPath:bundlePath];
    if (bundle) {
        broadcastPickerView.preferredExtension = bundle.bundleIdentifier;
        for (UIView *subView in broadcastPickerView.subviews) {
            if ([subView isMemberOfClass:[UIButton class]]) {
                UIButton *button = (UIButton *)subView;
                [button sendActionsForControlEvents:UIControlEventAllEvents];
            }
        }
    }
}
  • 苹果在 iOS 12.0 中新增了 RPSystemBroadcastPickerView,可以从 App 应用弹出启动器,供用户确认启动屏幕分享。但目前 RPSystemBroadcastPickerView 还不支持自定义界面,也没有官方的唤起方法。
  • 苹果官方不推荐该方案,并有可能在新一轮的系统更新中失效,因此只是一个可选方案,选用此方案您需要自行承担风险。

5.4 登录房间推流

完成上述屏幕共享源的采集过程后,将采集到的数据源推送到云服务器。(推送数据源的通道必须与设置采集源的通道保持一致)

[ZegoExpressEngine.sharedEngine startPublishingStream:streamID channel:ZegoPublishChannelMain];

6 观看远端屏幕共享

完成以上步骤后,其他用户可以使用 startPlayingStream 接口拉取屏幕共享流。

// 拉流播放,需传入发起屏幕共享的用户推流时所用的 streamID
[[ZegoExpressEngine sharedEngine] startPlayingStream:streamID canvas:[ZegoCanvas canvasWithView:self.playView]];

7 常见问题

  1. iOS 是否支持共享指定区域?

    iOS 系统仅支持共享整个屏幕,不支持共享指定区域。

  2. iOS 使用屏幕共享时进入后台,为什么会停止采集?

    • 在应用中开启音频录制的后台模式。
      /Pics/iOS/ZegoExpressEngine/ShareScreen/share_screen_background_mode.png
    • 若使用主路进行屏幕共享功能,SDK 将不会启动音频内部采集,无法进行后台保活,当应用退后台后,屏幕共享可能停止,建议对应用添加后台保活处理逻辑。
  3. iOS 使用屏幕共享时出现音频播放异常,如何处理?

    若使用屏幕共享功能采集并推流音频,同时又在本机使用拉流功能,会导致 iOS 系统重复采集拉流音频,导致音频播放异常,建议使用 muteAllPlayStreamAudio 禁止拉取所有音频流。