屏幕共享
在互动直播或视频通话中,主播或视频通话用户可以通过声网 SDK 中的屏幕共享特性,将自己的屏幕内容以视频的方式分享给其他用户或观众观看。
屏幕共享可以应用在以下场景中:
场景 | 描述 |
---|---|
在线教育 | 老师将自己的屏幕、教学课件、绘图软件或编程软件共享给学生,用于课堂示范 |
游戏直播 | 主播共享自己的游戏画面给观众 |
互动直播 | 主播共享自己的屏幕和观众互动 |
视频会议 | 会议成员共享屏幕观看 PPT 或者文档 |
远程控制 | 被控端向主控端展示自己的桌面 |
本文介绍如何使用声网 Unity SDK 4.x 在 Android,iOS,macOS 和 Windows 平台实现屏幕共享。
前提条件
在实现屏幕共享前,请确保已在你的项目中实现基本的实时音视频功能。详见实现音视频互动。
Android 平台
实现方法
本节介绍如何在 Android 平台上实现屏幕共享。
在 Android 平台实现屏幕共享时,只需要调用 StartScreenCapture
即可开启屏幕共享:
-
方案 1:在加入频道前调用
StartScreenCapture
,然后调用JoinChannel
[2/2] 加入频道并设置publishScreenCaptureVideo
为true
,即可开始屏幕共享。 -
方案 2:在加入频道后调用
StartScreenCapture
,然后调用UpdateChannelMediaOptions
设置publishScreenCaptureVideo
为true
,即可开始屏幕共享。
// 方案1:
// 加入频道前调用 StartScreenCapture 开启屏幕共享。
ScreenCaptureParameters2 screenCaptureParameters2 = new ScreenCaptureParameters2();
screenCaptureParameters2.captureVideo = true;
screenCaptureParameters2.captureAudio = true;
RtcEngine.StartScreenCapture(screenCaptureParameters2);
// 调用 JoinChannel 加入频道
ChannelMediaOptions channelMediaOptions = new ChannelMediaOptions();
channelMediaOptions.publishScreenCaptureVideo.SetValue(true);
channelMediaOptions.publishScreenCaptureAudio.SetValue(true);
channelMediaOptions.publishCameraTrack.SetValue(false);
channelMediaOptions.publishMicrophoneTrack.SetValue(false);
RtcEngine.JoinChannel("token", "channelId", uid, channelMediaOptions);
// 方案2:
// 调用 JoinChannel 加入频道。
RtcEngine.JoinChannel(_token, _channelName);
ScreenCaptureParameters2 screenCaptureParameters2 = new ScreenCaptureParameters2();
screenCaptureParameters2.captureVideo = true;
screenCaptureParameters2.captureAudio = true;
// 开启屏幕共享
RtcEngine.StartScreenCapture(screenCaptureParameters2);
ChannelMediaOptions channelMediaOptions = new ChannelMediaOptions();
channelMediaOptions.publishScreenCaptureVideo.SetValue(true);
channelMediaOptions.publishScreenCaptureAudio.SetValue(true);
channelMediaOptions.publishCameraTrack.SetValue(false);
channelMediaOptions.publishMicrophoneTrack.SetValue(false);
// 更新频道媒体选项
RtcEngine.UpdateChannelMediaOptions(channelMediaOptions);
API 参考
iOS 平台
- 受系统限制,屏幕共享只支持 iOS 12.0 或之后的系统。
- 该功能对设备性能要求较高,声网推荐你在 iPhone X 及之后机型上使用。
技术原理
iOS 端的屏幕共享是通过在 Extension 中使用 iOS 原生的 ReplayKit 框架实现录制屏幕,然后将屏幕共享流作为一个用户加入频道实现的。由于 Apple 不支持在主 App 进程采集屏幕,因此你需要为屏幕共享流单独创建一个 Extension。
实现方法
-
在 Unity Editor 中打包 iOS 项目,导出 Xcode 工程。
-
前往你的项目文件夹,用 Xcode 打开
unity-iphone/.xcodeproj
文件夹。 -
创建一个 Broadcast Upload Extension 用于开启屏幕共享的进程:
a. 在 Xcode 中,点击 File > New > Target..., 在弹出的窗口中选择 Broadcast Upload Extension, 点击 Next。
b. 在弹出的窗口中填写 Product Name 等信息,取消勾选 Include UI Extension,点击 Finish。Xcode 会自动创建该 Extension 的文件夹,其中包含
SampleHandler.h
文件。c. 在 Target 下选中刚创建的 Extension,点击 General,在 Deployment Info 下将 iOS 的版本设置为 12.0 或之后。
-
如果你只需使用声网提供的
AgoraReplayKitExtension.framework
中的功能,将Target
选择为刚刚创建的 Extension,在 Info 中选择 NSExtension > NSExtensionPrincipalClass, 将所对应的 Value 从 $(PRODUCT_MODULE_NAME}.SampleHandler 改为 AgoraReplayKitHandler。 -
如果你还需要自定义一些业务逻辑,修改方式为:将如下代码替换到
SampleHandler.h
文件中:Objective-C#import "SampleHandler.h"
#import "AgoraReplayKitExt.h"
#import <sys/time.h>
@interface SampleHandler () <AgoraReplayKitExtDelegate>
@end
@implementation SampleHandler
- (void)broadcastStartedWithSetupInfo:(NSDictionary<NSString *, NSObject *> *)setupInfo {
[[AgoraReplayKitExt shareInstance] start:self];
}
- (void)broadcastPaused {
NSLog(@"broadcastPaused");
[[AgoraReplayKitExt shareInstance] pause];
}
- (void)broadcastResumed {
NSLog(@"broadcastResumed");
[[AgoraReplayKitExt shareInstance] resume];
}
- (void)broadcastFinished {
NSLog(@"broadcastFinished");
[[AgoraReplayKitExt shareInstance] stop];
}
- (void)processSampleBuffer:(CMSampleBufferRef)sampleBuffer withType:(RPSampleBufferType)sampleBufferType {
[[AgoraReplayKitExt shareInstance] pushSampleBuffer:sampleBuffer withType:sampleBufferType];
}
#pragma mark - AgoraReplayKitExtDelegate
- (void)broadcastFinished:(AgoraReplayKitExt *_Nonnull)broadcast reason:(AgoraReplayKitExtReason)reason {
switch (reason) {
case AgoraReplayKitExtReasonInitiativeStop: {
// 自主停止
} break;
case AgoraReplayKitExtReasonConnectFail: {
// 连接失败
} break;
case AgoraReplayKitExtReasonDisconnect: {
// 断开连接
} break;
default:
break;
}
}
@end
-
-
在 TARGETS 中选中你创建的 Extension, 在 General/Frameworks and Libraries 中添加 Frameworks/Agora-RTC-Plugin/Agora-Unity-RTC-SDK/Plugins/iOS/ 路径下所有 Framework。
-
调用
StartScreenCapture
,并结合用户的手动操作,使 App 开启屏幕共享。例如:提示用户在 iOS 系统的控制中心长按屏幕录制按钮,并选择用你创建的 Extension 开启录制。
注意事项
- 请确保你的 App 和 Extension 有相同的 TARGETS/Deployment/iOS 版本。
- Broadcast Upload Extension 的内存使用限制为 50 MB,请确保屏幕共享的 Extension 内存使用不超过 50 MB。
API 参考
屏幕共享功能目前存在一些使用限制和注意事项,同时会产生费用,声网推荐你在调用 API 前先阅读如下 API 参考:
macOS 平台/Windows 平台
技术原理
Windows 或 macOS 系统为每个屏幕分配一个唯一的 Display ID,为每个窗口分配一个唯一的 Window ID,因此声网提供以下两种屏幕共享方案:
- 共享指定屏幕或指定屏幕的部分区域:调用
GetScreenCaptureSources
获取 Display ID,然后调用StartScreenCaptureByDisplayId
开始屏幕共享。 - 共享指定窗口或指定窗口的部分区域:调用
GetScreenCaptureSources
获取 Window ID,然后调用StartScreenCaptureByWindowId
开始屏幕共享。
实现方法
本节介绍如何在 macOS 和 Windows 平台实现屏幕共享。
-
获取可共享的屏幕和窗口列表。 调用
GetScreenCaptureSources
方法,获取需要共享屏幕的 Display ID 或窗口的 Window ID。C#SIZE thumbSize = new SIZE(360,240);
SIZE iconSize = new SIZE(360,240);
ScreenCaptureSourceInfo[] screenCaptureSourceInfos = RtcEngine.GetScreenCaptureSources(thumbSize, iconSize, true); -
共享指定屏幕或窗口。
根据共享对象的不同,调用
StartScreenCaptureByDisplayId
或StartScreenCaptureByWindowId
方法开始屏幕共享。C#ScreenCaptureSourceInfo info = screenCaptureSourceInfos[0];
if (info.type == ScreenCaptureSourceType.ScreenCaptureSourceType_Screen)
{
ulong displayId = info.sourceId;
RtcEngine.StartScreenCaptureByDisplayId((uint)displayId, default(Rectangle),default(ScreenCaptureParameters));
}
else if (info.type == ScreenCaptureSourceType.ScreenCaptureSourceType_Window)
{
ulong windowId = info.sourceId;
RtcEngine.StartScreenCaptureByWindowId(windowId, default(Rectangle),default(ScreenCaptureParameters));
} -
加入频道并发布屏幕共享流。
信息- 如果你想在共享屏幕的同时共享屏幕采集的音频,你需要调用
EnableLoopbackRecording
开启声卡采集功能,将声卡播放的声音合并到本地音频流中。 - 调用该方法后,系统其他进程播放的音频也会被发布到远端,如果这并非你的预期,请再次调用该方法,关闭声卡采集。
-
如果仅需发布屏幕共享流,在你的项目中添加如下代码:
C#ChannelMediaOptions options = new ChannelMediaOptions();
options.publishCameraTrack.SetValue(false);
options.publishScreenTrack.SetValue(true);
#if UNITY_ANDROID || UNITY_IPHONE
options.publishScreenCaptureAudio.SetValue(true);
options.publishScreenCaptureVideo.SetValue(true);
#endif
#if UNITY_EDITOR_WIN || UNITY_EDITOR_OSX || UNITY_STANDALONE_WIN || UNITY_STANDALONE_OSX
// 对于 Windows 和 macOS 平台,如果你需要在共享视频时,同时共享视频的声音,还需要添加以下代码
// ret = RtcEngine.EnableLoopbackRecording(true, "");
// Debug.Log("EnableLoopbackRecording returns: " + ret);
#endif
RtcEngine.UpdateChannelMediaOptions(options); -
如需发布屏幕共享流和本地摄像头采集的视频流,在你的项目中添加如下代码:
C#// 加入一路频道并且推送摄像头流
RtcEngine.EnableAudio();
RtcEngine.EnableVideo();
RtcEngine.SetClientRole(CLIENT_ROLE_TYPE.CLIENT_ROLE_BROADCASTER);
ChannelMediaOptions options = new ChannelMediaOptions();
options.autoSubscribeAudio.SetValue(true);
options.autoSubscribeVideo.SetValue(true);
options.publishCameraTrack.SetValue(true);
options.publishScreenTrack.SetValue(false);
options.enableAudioRecordingOrPlayout.SetValue(true);
options.clientRoleType.SetValue(CLIENT_ROLE_TYPE.CLIENT_ROLE_BROADCASTER);
RtcEngine.JoinChannel(_token, _channelName, this.Uid1, options);
// 加入一路频道并且推送屏幕共享流
ChannelMediaOptions options = new ChannelMediaOptions();
options.autoSubscribeAudio.SetValue(false);
options.autoSubscribeVideo.SetValue(false);
options.publishCameraTrack.SetValue(false);
options.publishScreenTrack.SetValue(true);
options.enableAudioRecordingOrPlayout.SetValue(false);
#if UNITY_ANDROID || UNITY_IPHONE
options.publishScreenCaptureAudio.SetValue(true);
options.publishScreenCaptureVideo.SetValue(true);
#endif
options.clientRoleType.SetValue(CLIENT_ROLE_TYPE.CLIENT_ROLE_BROADCASTER);
var ret = RtcEngine.JoinChannelEx(_token, new RtcConnection(_channelName, this.Uid2), options);
- 如果你想在共享屏幕的同时共享屏幕采集的音频,你需要调用
参考信息
功能介绍
声网 SDK 的屏幕共享特性可提供以下功能,适用于各种场景下的屏幕共享。
屏幕共享功能在各平台的适用情况如下:
- 桌面端(Windows 和 macOS):支持上述所有屏幕共享功能。
- 移动端(Android 和 iOS):仅支持共享整个屏幕。
共享整个屏幕
将你的整个屏幕进行共享,包括屏幕中的所有信息,该功能支持同时采集两块屏幕的信息并共享。
共享 App 窗口
如果你不希望将整个屏幕内容分享给其他用户,可以只共享一个 App 窗口中的画面。
共享指定区域
如果你只希望共享屏幕或 App 窗口中的一部分,可以在开启屏幕共享时设置一个共享区域,只有该区域内的画面会被分享。
高级功能
除上述功能外,你还可以在开启屏幕共享时通过调整参数,实现以下高级共享功能:
- 屏蔽指定 App 窗口:在共享屏幕时,如果你不希望暴露某个 App 窗口,可以选择将该 App 窗口屏蔽,则该窗口将不会出现在共享的屏幕中。
- 描边:如果你需要勾勒出正在共享的范围,可以对指定的 App 窗口或屏幕进行描边,并自定义描边的宽度、颜色和透明度。
- 前置指定 App 窗口:如果你同时共享了多个 App 窗口,可能会出现窗口之间互相遮挡的情况,你可以指定一个 App 窗口并将其前置,即可避免它被其他窗口遮挡。
- 设置共享场景:SDK 会根据你设置的场景自动调节 QOE (Quality of Experience) 策略。
- 在共享文档、幻灯片、表格,或者远程控制时,你可以将共享场景设置为文档场景或远程控制场景,SDK 会优先保障画质,并降低接收端看共享视频的延时。
- 在共享游戏或电影、视频直播时,你可以将共享场景设置为游戏场景或视频场景,SDK 会优先保障流畅性。
优势介绍
声网提供的屏幕共享特性具备以下优势:
超高清画质体验
支持超高清视频(分辨率为 4K,帧率为 60 fps),给用户带来更加流畅、高清的极致画面体验。
多 App 支持
适配 WPS Office、Microsoft Office Power Point、Visual Studio Code、Adobe Photoshop、Windows Media Player 和 Scratch 等多款主流 App,方便用户在屏幕共享时直接共享指定 App、提升了功能易用性。
多设备支持
支持多设备同时共享,兼容 Windows 8 系统、无独立显卡的设备、双显卡设备、外接屏幕设备等,满足各种场景下的设备使用需求。
多平台适配
支持 iOS、Andriod、macOS、Windows、Web、Unity、Flutter、React Native、Unreal Engine 等平台。
高安全保障
支持仅共享 App 和屏幕中的部分区域内容,并支持屏蔽指定 App 窗口,有效保障用户信息安全。
注意事项
在开启屏幕共享后,声网以屏幕共享视频流的分辨率作为计费标准。PC 端屏幕共享流默认分辨率为 1920 x 1080,移动端屏幕共享流默认分辨率为 1280 x 720。你也可以根据你的业务需求进行调整。详见如何确定屏幕共享视频流的分辨率?
示例项目
声网提供了开源的屏幕共享示例项目供你参考,你可以前往下载或查看其中的源代码。