iOS音视频接入 - TRTC实时屏幕分享

时间:2022-07-26
本文章向大家介绍iOS音视频接入 - TRTC实时屏幕分享,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

什么是实时屏幕分享?

解为实时的将我们PC、手机屏幕上的内容分享给其他人员观看。在我们常见的使用场景有PC端和移动端的游戏直播、远程会议的项目演示等

iOS屏幕录制系统库

使用ReplayKit实现屏幕录制(iOS 9.0+)

ReplayKit2在实现上做了大量提升(iOS 11+)

实时屏幕分享基本流程

以iOS为例:

  1. 在主App(或扩展程序内)录制屏幕
  2. 在主App内将录制的视频通过网络推送出去
  3. 远端用户观看分享

支持的平台

iOS

Android

Mac OS

Windows

Electron

微信小程序

Chrome 浏览器

×

iOS实时屏幕分享类型

应用内分享

即只能分享当前 App (也成宿主程序)的画面,该特性需要 iOS 13 及以上版本的操作系统才能支持。由于无法分享当前 App 之外的屏幕内容,因此适用于对隐私保护要求高的场景。

代码实现步骤

应用内分享的方案非常简单,只需要调用 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)是指画面在剧烈变化时的最高输出码率,如果屏幕内容变化较少,实际编码码率会比较低。

注意点

主App限制内存占用为1G。

跨应用分享

基于苹果的 Replaykit 方案,能够分享整个系统的屏幕内容,但需要当前 App 额外提供一个 Extension 扩展组件,因此对接步骤也相对应用内分享要多一点。

腾讯在TRTCSDK内部为我们提供了跨应用分享的Demo,Demo的位置如下图

跨应用分享的Demo

内部实现

扩展程序通过ReplayKit采集屏幕数据(只采集屏幕数据),在主程序内部创建一个本地socket服务,扩展程序本地创建一个socket,通过socket将采集的视频推给主程序,主程序在推出去,可避免在扩展程序内部做太多事情,而导致被系统杀掉。

注意点

Extension 扩展组件占用内存为50兆,如超过此内存限制,系统会杀掉这个扩展。、

如果想要跑通这个Demo你必须有一个已付费的苹果开发者账号,个人未付费账号暂时无法跑通此Demo。付费账号配置证书如下:

跨应用分享证书配置

创建App Group

使用您的帐号登录 develop.apple.com ,进行以下操作,注意完成后需要重新下载对应的 Provisioning Profile

  1. 单击【Certificates, IDs & Profiles】。
  2. 在右侧的界面中单击加号。
  3. 选择【App Groups】,单击【Continue】。
  4. 在弹出的表单中填写 Description 和 Identifier, 其中 Identifier 需要传入接口中的对应的 AppGroup 参数。完成后单击【Continue】。
创建App Group

5. 回到 Identifier 页面,左上边的菜单中选择【App IDs】,然后单击您的 App ID(主 App 与 Extension 的 AppID 需要进行同样 的配置)。

6. 选中【App Groups】并单击【Edit】。

7. 在弹出的表单中选择您之前创建的 App Group,单击【Continue】返回编辑页,单击【Save】保存。

关联主App

8.重新下载 Provisioning Profile 并配置到 XCode 中。

创建 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】,如下图:
App Groups创建

操作完成后,会在文件列表中生成一个名为Target名.entitlements的文件,如下图所示,选中该文件并单击 + 号填写上述步骤中的 App Group 即可。

entitlements文件

5. 选中主 App 的 Target ,并按照上述步骤对主 App 的 Target 做同样的处理。

6. 在新创建的 Target 中,Xcode 会自动创建一个名为 "SampleHandler.m" 的文件,用如下代码进行替换。需将代码中的 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】第4步的创建的 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)boradcastFinished:(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] sendVideoSampleBuffer:sampleBuffer];
            break;
        case RPSampleBufferTypeAudioApp:
            // Handle audio sample buffer for app audio
            break;
        case RPSampleBufferTypeAudioMic:
            // Handle audio sample buffer for mic audio
            break;

        default:
            break;
    }
}
@end

对接主 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:videoEncConfig
                                                     appGroup:APPGROUP];
}

// 停止屏幕分享
- (void)stopScreenCapture {
    [[TRTCCloud sharedInstance] stopScreenCapture];
}

// 屏幕分享的启动事件通知,可以通过 TRTCCloudDelegate 进行接收
- (void)onScreenCaptureStarted {
    [self showTip:@"屏幕分享开始"];
}

屏幕分享还必须要用户从控制中心中长按录屏按钮来手动启动,那么如何实现类似腾讯会议的点击按钮即可触发的效果呢?

腾讯会议触发分享

我们可以在上述的Demo中查找TRTCBroadcastExtensionLauncher类,并将其加入自己的工程内部。在我们想要唤起的函数中调用以下方法,即可将屏幕分享功能唤起。

[TRTCBroadcastExtensionLauncher launch];

注意:

苹果在 iOS 12.0 中增加了 RPSystemBroadcastPickerView 可以从应用中弹出启动器供用户确认启动屏幕分享,到目前为止, RPSystemBroadcastPickerView 尚不支持自定义界面,也没有官方的唤起方法。 TRTCBroadcastExtensionLauncher 的原理就是遍历 RPSystemBroadcastPickerView 的子 View 寻找 UIButton 并触发了其点击事件。 但该方案不被苹果官方推荐,并可能在新一轮的系统更新中失效,因此实现【增加屏幕分享的触发按钮】方式只是一个可选方案,您需要自行承担风险来选用此方案。

观看屏幕分享

若用户通过 Android / iOS 进行屏幕分享,会通过主流进行分享。房间里的其他用户会通过 TRTCCloudDelegate 中的onUserVideoAvailable事件获得这个通知。

希望观看屏幕分享的用户可以通过startRemoteView接口来启动渲染远端用户主流画面。