开启屏幕共享
腾讯云 TRTC 在 iOS 平台下支持两种不同的屏幕分享方案:
应用内分享
即只能分享当前 App 的画面,该特性需要 iOS 13 及以上版本的操作系统才能支持。由于无法分享当前 App 之外的屏幕内容,因此适用于对隐私保护要求高的场景。
跨应用分享
基于苹果的 Replaykit 方案,能够分享整个系统的屏幕内容,但需要当前 App 额外提供一个 Extension 扩展组件,因此对接步骤也相对应用内分享要多一点。
支持的平台
iOS | Android | Mac OS | Windows | Electron | Chrome 浏览器 |
✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
应用内分享
应用内分享的方案非常简单,只需要调用 TRTC SDK 提供的接口 startScreenCaptureInApp 并传入编码参数
TRTCVideoEncParam
即可。该参数可以设置为 nil,此时 SDK 会沿用开始屏幕分享之前的编码参数。我们推荐的用于 iOS 屏幕分享的编码参数是:
参数项 | 参数名称 | 常规推荐值 | 文字教学场景 |
分辨率 | videoResolution | 1280 × 720 | 1920 × 1080 |
帧率 | videoFps | 10 FPS | 8 FPS |
最高码率 | videoBitrate | 1600 kbps | 2000 kbps |
分辨率自适应 | enableAdjustRes | NO | NO |
由于屏幕分享的内容一般不会剧烈变动,所以设置较高的 FPS 并不经济,推荐10 FPS即可。
如果您要分享的屏幕内容包含大量文字,可以适当提高分辨率和码率设置。
最高码率(videoBitrate)是指画面在剧烈变化时的最高输出码率,如果屏幕内容变化较少,实际编码码率会比较低。
跨应用分享
iOS 系统上的跨应用屏幕分享,需要增加 Broadcast Upload Extension 录屏进程以配合主 App 进程进行推流。Extension 录屏进程由系统在需要录屏的时候创建,并负责接收系统采集到屏幕图像。因此需要:
1. 创建 App Group,并在 XCode 中进行配置(可选)。这一步的目的是让 Extension 录屏进程可以同主 App 进程进行跨进程通信。
2. 在您的工程中,新建一个 Broadcast Upload Extension 的 Target,并在其中集成 SDK 压缩包中专门为扩展模块定制的
TXLiteAVSDK_ReplayKitExt.framework
。3. 对接主 App 端的接收逻辑,让主 App 等待来自 Broadcast Upload Extension 的录屏数据。
注意:
如果跳过步骤1,也就是不配置 App Group(接口传 nil),屏幕分享依然可以运行,但稳定性要打折扣,故虽然步骤较多,但请尽量配置正确的 App Group 以保障屏幕分享功能的稳定性。
步骤1:创建 App Group
1. 单击 Certificates, IDs & Profiles。
2. 在右侧的界面中单击加号。
3. 选择 App Groups,单击 Continue。
4. 在弹出的表单中填写 Description 和 Identifier,其中 Identifier 需要传入接口中的对应的 AppGroup 参数。完成后单击 Continue。
5. 回到 Identifier 页面,左上边的菜单中选择 App IDs,然后单击您的 App ID(主 App 与 Extension 的 AppID 需要进行同样的配置)。
6. 选中 App Groups 并单击 Edit。
7. 在弹出的表单中选择您之前创建的 App Group,单击 Continue 返回编辑页,单击 Save 保存。
8. 重新下载 Provisioning Profile 并配置到 XCode 中。
步骤2:创建 Broadcast Upload Extension
1. 在 Xcode 菜单依次单击 File、New 、Target...,选择 Broadcast Upload Extension。
2. 在弹出的对话框中填写相关信息,不用勾选 Include UI Extension,单击 Finish 完成创建。
3. 将下载到的 SDK 压缩包中的 TXLiteAVSDK_ReplayKitExt.framework 拖动到工程中,勾选刚创建的 Target。
4. 选中新增加的 Target,依次单击 + Capability,双击 App Groups,如下图:
操作完成后,会在文件列表中生成一个名为
Target名.entitlements
的文件,如下图所示,选中该文件并单击 + 号填写上述步骤中的 App Group 即可。
5. 选中主 App 的 Target ,并按照上述步骤对主 App 的 Target 做同样的处理。
6. 在新创建的 Target 中,Xcode 会自动创建一个名为 "SampleHandler.h" 的文件,用如下代码进行替换。需将代码中的 APPGROUP 改为上文中的创建的 App Group Identifier。
#import "SampleHandler.h"@import TXLiteAVSDK_ReplayKitExt;#define APPGROUP @"group.com.tencent.liteav.RPLiveStreamShare"@interface SampleHandler() <TXReplayKitExtDelegate>@end@implementation SampleHandler// 注意:此处的 APPGROUP 需要改成上文中的创建的 App Group Identifier。- (void)broadcastStartedWithSetupInfo:(NSDictionary<NSString *,NSObject *> *)setupInfo {[[TXReplayKitExt sharedInstance] setupWithAppGroup:APPGROUP delegate:self];}- (void)broadcastPaused {// User has requested to pause the broadcast. Samples will stop being delivered.}- (void)broadcastResumed {// User has requested to resume the broadcast. Samples delivery will resume.}- (void)broadcastFinished {[[TXReplayKitExt sharedInstance] finishBroadcast];// User has requested to finish the broadcast.}#pragma mark - TXReplayKitExtDelegate- (void)broadcastFinished:(TXReplayKitExt *)broadcast reason:(TXReplayKitExtReason)reason{NSString *tip = @"";switch (reason) {case TXReplayKitExtReasonRequestedByMain:tip = @"屏幕共享已结束";break;case TXReplayKitExtReasonDisconnected:tip = @"应用断开";break;case TXReplayKitExtReasonVersionMismatch:tip = @"集成错误(SDK 版本号不相符合)";break;}NSError *error = [NSError errorWithDomain:NSStringFromClass(self.class)code:0userInfo:@{NSLocalizedFailureReasonErrorKey:tip}];[self finishBroadcastWithError:error];}- (void)processSampleBuffer:(CMSampleBufferRef)sampleBuffer withType:(RPSampleBufferType)sampleBufferType {switch (sampleBufferType) {case RPSampleBufferTypeVideo:[[TXReplayKitExt sharedInstance] sendVideoSampleBuffer:sampleBuffer];break;case RPSampleBufferTypeAudioApp:// Handle audio sample buffer for app audiobreak;case RPSampleBufferTypeAudioMic:// Handle audio sample buffer for mic audiobreak;default:break;}}@end
步骤3:对接主 App 端的接收逻辑
按照如下步骤,对接主 App 端的接收逻辑。也就是在用户触发屏幕分享之前,要让主 App 处于“等待”状态,以便随时接收来自 Broadcast Upload Extension 进程的录屏数据。
1. 确保 TRTCCloud 已经关闭了摄像头采集,如果尚未关闭,请调用 stopLocalPreview 关闭摄像头采集。
2. 调用 startScreenCaptureByReplaykit:appGroup: 方法,并传入 步骤1 中设置的 AppGroup,让 SDK 进入“等待”状态。
3. 等待用户触发屏幕分享。如果不实现 步骤4 中的“触发按钮”,屏幕分享就需要用户在 iOS 系统的控制中心,通过长按录屏按钮来触发,这一操作步骤如下图所示:
4. 通过调用 stopScreenCapture 接口可以随时中止屏幕分享。
// 开始屏幕分享,需要将 APPGROUP 替换为上述步骤中创建的 App Group Identifier。- (void)startScreenCapture {TRTCVideoEncParam *videoEncConfig = [[TRTCVideoEncParam alloc] init];videoEncConfig.videoResolution = TRTCVideoResolution_1280_720;videoEncConfig.videoFps = 10;videoEncConfig.videoBitrate = 2000;//需要将 APPGROUP 替换为上述步骤中创建的 App Group Identifier:[[TRTCCloud sharedInstance] startScreenCaptureByReplaykit:videoEncConfigappGroup:APPGROUP];}// 停止屏幕分享- (void)stopScreenCapture {[[TRTCCloud sharedInstance] stopScreenCapture];}// 屏幕分享的启动事件通知,可以通过 TRTCCloudDelegate 进行接收- (void)onScreenCaptureStarted {[self showTip:@"屏幕分享开始"];}
步骤4:增加屏幕分享的触发按钮(可选)
1. 在 Demo 中的 TRTCBroadcastExtensionLauncher 文件实现了唤起屏幕分享,找到并将其加入到您的工程中。
2. 在您的界面上放置一个按钮,并在按钮的响应函数中调用
TRTCBroadcastExtensionLauncher
中的 launch
函数,就可以唤起屏幕分享功能了。// 自定义按钮响应方法- (IBAction)onScreenButtonTapped:(id)sender {[TRTCBroadcastExtensionLauncher launch];}
注意:
苹果在 iOS 12.0 中增加了
RPSystemBroadcastPickerView
可以从应用中弹出启动器供用户确认启动屏幕分享,到目前为止, RPSystemBroadcastPickerView
尚不支持自定义界面,也没有官方的唤起方法。TRTCBroadcastExtensionLauncher 的原理就是遍历
RPSystemBroadcastPickerView
的子 View 寻找 UIButton 并触发了其点击事件。但该方案不被苹果官方推荐,并可能在新一轮的系统更新中失效,因此 步骤4 只是一个可选方案,您需要自行承担风险来选用此方案。
观看屏幕分享
观看 Mac / Windows 屏幕分享
当房间里有一个 Mac / Windows 用户启动了屏幕分享,会通过辅流进行分享。房间里的其他用户会通过 TRTCCloudDelegate 中的 onUserSubStreamAvailable 事件获得这个通知。
希望观看屏幕分享的用户可以通过 startRemoteSubStreamView 接口来启动渲染远端用户辅流画面。
观看 Android / iOS 屏幕分享
若用户通过 Android / iOS 进行屏幕分享,会通过主流进行分享。房间里的其他用户会通过 TRTCCloudDelegate 中的 onUserVideoAvailable 事件获得这个通知。
希望观看屏幕分享的用户可以通过 startRemoteView 接口来启动渲染远端用户主流画面。