tencent cloud

文档反馈

Android&iOS&Flutter

最后更新时间:2024-12-27 10:04:17
    本文档将详细介绍TUIRoomKit屏幕共享功能,帮助您更好地掌握TUIRoomKit会议过程中的屏幕共享相关功能操作。通过本文档,您能够充分利用TUIRoomKit的功能,实现高质量的音视频会议。 若 TUIRoomKit 的 UI 交互不满足您的产品需求,您有自己的交互和业务逻辑需要自定义实现屏幕共享 相关的交互功能,可以接入 TUIRoomEngineSDK 调用来实现您的需求。

    功能介绍

    TUIRoomKit 支持屏幕共享,用户可以在进入房间之后分享自己的屏幕,房间内的其他成员可以观看正在分享中的屏幕。本文将详细介绍该特性的相关功能,并说明如何在 TUIRoomKit 组件中使用这一特性。

    使用说明

    Android&iOS&Flutter端用户进入房间后,通过点击底部工具栏共享按钮,可以实现屏幕共享操作。
    屏幕分享
    
    
    

    功能接入

    在接入屏幕共享功能时,您可能需要进行一些配置。不同平台的配置方法请参见:
    Android
    iOS
    Flutter
    由于 Android 系统隐私策略的更改,在 Android 10 及以上版本 App 若使用录屏等功能需要在前台 Service 中进行,否则录屏/屏幕共享时系统将报错或 App 被系统终止。在我们的组件中,会自动为您开启该 Android Foreground Service您只需要点击屏幕共享按钮,同意相关隐私政策后即可进行共享。
    Android Foreground Service 相关代码可参见我们的 代码示例
    iOS 系统上的跨应用屏幕分享,需要增加 Extension 录屏进程以配合主 App 进程进行推流。Extension 录屏进程由系统在需要录屏的时候创建,并负责接收系统采集到屏幕图像。因此需要:
    1. 创建 App Group,并在 XCode 中进行配置(可选)。这一步的目的是让 Extension 录屏进程可以同主 App 进程进行跨进程通信。
    2. 在您的工程中,新建一个 Broadcast Upload Extension 的 Target,并在其中集成 SDK 压缩包中专门为扩展模块定制的 TXLiteAVSDK_ReplayKitExt.framework
    3. 点击屏幕分享按钮,开始分享您的屏幕。
    注意:
    如果跳过 步骤1,也就是不配置 App Group(接口传 null),屏幕分享依然可以运行,但稳定性要打折扣,故虽然步骤较多,但请尽量配置正确的 App Group 以保障屏幕分享功能的稳定性。

    步骤1:
    创建 App Group(可选)
    

    使用您的账号 登录,进行以下操作,注意完成后需要重新下载对应的 Provisioning Profile。
    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. 如果选择执行 步骤1,需要在新增加的 Target 中,依次单击 + Capability,双击 App Groups,如下图:
    
    AddCapability
    
    
    操作完成后,会在文件列表中生成一个名为 Target.entitlements 的文件,如下图所示,选中该文件并单击 + 号填写上述步骤中的 App Group 即可。
    
    AddGroup
    
    
    5. 选中主 App 的 Target ,并按照上述步骤对主 App 的 Target 做同样的处理。
    6. 在新创建的 Target 中,Xcode 会自动创建一个名为 "SampleHandler.swift" 的文件,用如下代码进行替换。如果执行了步骤1,请将代码中的 APPGROUP 替换为之前创建的 App Group Identifier, 然后找到 TUIRoomKit中的 EngineManager.swift 文件,将其中的appGroupString 也设置为 App Group Identifier。如果 步骤1 被跳过,则不需要修改 APPGROUP。
    Swift
    OC
    import ReplayKit
    import TXLiteAVSDK_ReplayKitExt
    
    let APPGROUP = "group.com.tencent.comm.trtc.demo"
    
    class SampleHandler: RPBroadcastSampleHandler, TXReplayKitExtDelegate {
    
    let recordScreenKey = Notification.Name.init("TRTCRecordScreenKey")
    
    override func broadcastStarted(withSetupInfo setupInfo: [String : NSObject]?) {
    // User has requested to start the broadcast. Setup info from the UI extension can be supplied but optional.
    TXReplayKitExt.sharedInstance().setup(withAppGroup: APPGROUP, delegate: self)
    }
    
    override func broadcastPaused() {
    // User has requested to pause the broadcast. Samples will stop being delivered.
    }
    
    override func broadcastResumed() {
    // User has requested to resume the broadcast. Samples delivery will resume.
    }
    
    override func broadcastFinished() {
    // User has requested to finish the broadcast.
    TXReplayKitExt.sharedInstance().broadcastFinished()
    }
    
    func broadcastFinished(_ broadcast: TXReplayKitExt, reason: TXReplayKitExtReason) {
    var tip = ""
    switch reason {
    case TXReplayKitExtReason.requestedByMain:
    tip = "屏幕共享已结束"
    break
    case TXReplayKitExtReason.disconnected:
    tip = "应用断开"
    break
    case TXReplayKitExtReason.versionMismatch:
    tip = "集成错误(SDK 版本号不相符合)"
    break
    default:
    break
    }
    
    let error = NSError(domain: NSStringFromClass(self.classForCoder), code: 0, userInfo: [NSLocalizedFailureReasonErrorKey:tip])
    finishBroadcastWithError(error)
    }
    
    override func processSampleBuffer(_ sampleBuffer: CMSampleBuffer, with sampleBufferType: RPSampleBufferType) {
    switch sampleBufferType {
    case RPSampleBufferType.video:
    // Handle video sample buffer
    TXReplayKitExt.sharedInstance() .sendVideoSampleBuffer(sampleBuffer)
    break
    case RPSampleBufferType.audioApp:
    // Handle audio sample buffer for app audio
    break
    case RPSampleBufferType.audioMic:
    // Handle audio sample buffer for mic audio
    break
    @unknown default:
    // Handle other sample buffer types
    fatalError("Unknown type of sample buffer")
    }
    }
    }
    #import "SampleHandler.h"
    @import TXLiteAVSDK_ReplayKitExt;
    #define APPGROUP @"group.com.tencent.comm.trtc.demo"
    
    @protocol TXReplayKitExtDelegate;
    @interface SampleHandler()
    @end
    
    @implementation SampleHandler
    
    - (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] broadcastFinished];
    // 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:0
    userInfo:@{
    NSLocalizedFailureReasonErrorKey:tip
    }];
    [self finishBroadcastWithError:error];
    }
    
    - (void)processSampleBuffer:(CMSampleBufferRef)sampleBuffer withType:(RPSampleBufferType)sampleBufferType {
    switch (sampleBufferType) {
    case RPSampleBufferTypeVideo:
    [[TXReplayKitExt sharedInstance] sendSampleBuffer:sampleBuffer withType:sampleBufferType];
    break;
    case RPSampleBufferTypeAudioApp:
    // Handle audio sample buffer for app audio
    break;
    case RPSampleBufferTypeAudioMic:
    // Handle audio sample buffer for mic audio
    break;
    default:
    // Handle other sample buffer types
    break;
    }
    }
    
    @end
    7. 点击新创建的 Target, 选择 General 选项并且在 Frameworks and Libraries 中添加下面的库:
    
    
    
    Android:由于 Android 系统隐私策略的更改,在 Android 10 及以上版本 App 若使用录屏等功能需要在前台 Service 中进行,否则录屏/屏幕共享时系统将报错或 App 被系统终止。在我们的组件中,会自动为您开启该 Android Foreground Service您只需要点击屏幕共享按钮,同意相关隐私政策后即可进行共享。
    Android Foreground Service 相关代码可参见我们的 代码示例
    
    iOS:iOS 系统上的跨应用屏幕分享,需要增加 Extension 录屏进程以配合主 App 进程进行推流。Extension 录屏进程由系统在需要录屏的时候创建,并负责接收系统采集到屏幕图像。因此需要:
    1. 创建 App Group,并在 XCode 中进行配置(可选)。这一步的目的是让 Extension 录屏进程可以同主 App 进程进行跨进程通信。
    2. 在您的工程中,新建一个 Broadcast Upload Extension 的 Target,并在其中集成 SDK 压缩包中专门为扩展模块定制的 TXLiteAVSDK_ReplayKitExt.framework
    3. 在组件中使用您的 App Group 和 BroadCast Upload Extension name 替换我们应用的 App Group 和 BroadCast Upload Extension name ,代码位置请点击 文件链接
    4. 点击屏幕分享按钮,开始分享您的屏幕。
    注意:
    如果跳过 步骤1,也就是不配置 App Group(接口传 null),屏幕分享依然可以运行,但稳定性要打折扣,故虽然步骤较多,但请尽量配置正确的 App Group 以保障屏幕分享功能的稳定性。

    步骤1:创建 App Group

    使用您的账号 登录,进行以下操作,注意完成后需要重新下载对应的 Provisioning Profile。
    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,如下图:
    
    AddCapability
    
    
    
    操作完成后,会在文件列表中生成一个名为Target.entitlements。
    的文件,如下图所示,选中该文件并单击 + 号填写上述步骤中的 App Group 即可。
    
    AddGroup
    
    
    5. 选中主 App 的 Target ,并按照上述步骤对主 App 的 Target 做同样的处理。
    6. 在新创建的 Target 中,Xcode 会自动创建一个名为 "SampleHandler.swift" 的文件,用如下代码进行替换。需将代码中的 APPGROUP 改为上文中的创建的 App Group Identifier。
    
    import ReplayKit
    import TXLiteAVSDK_ReplayKitExt
    
    let APPGROUP = "group.com.tencent.comm.trtc.demo"
    
    class SampleHandler: RPBroadcastSampleHandler, TXReplayKitExtDelegate {
    
    let recordScreenKey = Notification.Name.init("TRTCRecordScreenKey")
    
    override func broadcastStarted(withSetupInfo setupInfo: [String : NSObject]?) {
    // User has requested to start the broadcast. Setup info from the UI extension can be supplied but optional.
    TXReplayKitExt.sharedInstance().setup(withAppGroup: APPGROUP, delegate: self)
    }
    
    override func broadcastPaused() {
    // User has requested to pause the broadcast. Samples will stop being delivered.
    }
    
    override func broadcastResumed() {
    // User has requested to resume the broadcast. Samples delivery will resume.
    }
    
    override func broadcastFinished() {
    // User has requested to finish the broadcast.
    TXReplayKitExt.sharedInstance() .finishBroadcast()
    }
    
    func broadcastFinished(_ broadcast: TXReplayKitExt, reason: TXReplayKitExtReason) {
    var tip = ""
    switch reason {
    case TXReplayKitExtReason.requestedByMain:
    tip = "屏幕共享已结束"
    break
    case TXReplayKitExtReason.disconnected:
    tip = "应用断开"
    break
    case TXReplayKitExtReason.versionMismatch:
    tip = "集成错误(SDK 版本号不相符合)"
    break
    default:
    break
    }
    
    let error = NSError(domain: NSStringFromClass(self.classForCoder), code: 0, userInfo: [NSLocalizedFailureReasonErrorKey:tip])
    finishBroadcastWithError(error)
    }
    
    override func processSampleBuffer(_ sampleBuffer: CMSampleBuffer, with sampleBufferType: RPSampleBufferType) {
    switch sampleBufferType {
    case RPSampleBufferType.video:
    // Handle video sample buffer
    TXReplayKitExt.sharedInstance() .sendVideoSampleBuffer(sampleBuffer)
    break
    case RPSampleBufferType.audioApp:
    // Handle audio sample buffer for app audio
    break
    case RPSampleBufferType.audioMic:
    // Handle audio sample buffer for mic audio
    break
    @unknown default:
    // Handle other sample buffer types
    fatalError("Unknown type of sample buffer")
    }
    }
    }.
    步骤3:在组件中使用您的 App Group 和 BroadCast Upload Extension name 替换我们应用的 App Group 和 BroadCast Upload Extension name ,代码位置请点击 文件链接
    
    
    
    步骤4:点击屏幕分享按钮,开始分享您的屏幕。

    关键代码

    若您想自定义实现屏幕共享功能,请参见 TUIRoomEngine SDK:AndroidiOS&MacFlutter
    说明:
    您在接入或使用过程有任何疑问或者建议,欢迎联系:info_rtc@tencent.com 。
    联系我们

    联系我们,为您的业务提供专属服务。

    技术支持

    如果你想寻求进一步的帮助,通过工单与我们进行联络。我们提供7x24的工单服务。

    7x24 电话支持