开启屏幕共享

基于 Android 平台

腾讯云 TRTC 在 Android 系统上支持屏幕分享,即将当前系统的屏幕内容通过 TRTC SDK 分享给房间里的其他用户。关于此功能,有两点需要注意:
移动端 TRTC Android 8.6 之前的版本屏幕分享并不像桌面端版本一样支持“辅路分享”,因此在启动屏幕分享时,摄像头的采集需要先被停止,否则会相互冲突;8.6 及之后的版本支持“辅路分享”,则不需要停止摄像头的采集。
当一个 Android 系统上的后台 App 在持续使用 CPU 时,很容易会被系统强行杀掉,而且屏幕分享本身又必然会消耗 CPU。要解决这个看似矛盾的冲突,我们需要在 App 启动屏幕分享的同时,在 Android 系统上弹出悬浮窗。由于 Android 不会强杀包含前台 UI 的 App 进程,因此该种方案可以让您的 App 可以持续进行屏幕分享而不被系统自动回收。如下图所示:


启动屏幕分享

要开启 Android 端的屏幕分享,只需调用 TRTCCloud 中的 startScreenCapture() 接口即可。但如果要达到稳定和清晰的分享效果,您需要关注如下问题:

添加 Activity

在 manifest 文件中粘贴如下 activity(若项目代码中存在则不需要添加)。
<activity
android:name="com.tencent.rtmp.video.TXScreenCapture$TXScreenCaptureAssistantActivity"
android:theme="@android:style/Theme.Translucent"/>

设定视频编码参数

通过设置 startScreenCapture() 参数 encParams ,您可以指定屏幕分享的编码质量。如果您指定 encParams 为 null,SDK 会自动使用之前设定的编码参数,我们推荐的参数设定如下:
参数项
参数名称
常规推荐值
文字教学场景
分辨率
videoResolution
1280 × 720
1920 × 1080
帧率
videoFps
10 FPS
8 FPS
最高码率
videoBitrate
1600 kbps
2000 kbps
分辨率自适应
enableAdjustRes
NO
NO
说明:
由于屏幕分享的内容一般不会剧烈变动,所以设置较高的 FPS 并不经济,推荐10 FPS 即可。
如果您要分享的屏幕内容包含大量文字,可以适当提高分辨率和码率设置。
最高码率(videoBitrate)是指画面在剧烈变化时的最高输出码率,如果屏幕内容变化较少,实际编码码率会比较低。

基于 iOS 平台

即只能分享当前 App 的画面,该特性需要 iOS 13 及以上版本的操作系统才能支持。由于无法分享当前 App 之外的屏幕内容,因此适用于对隐私保护要求高的场景。
基于苹果的 Replaykit 方案,能够分享整个系统的屏幕内容,但需要当前 App 额外提供一个 Extension 扩展组件,因此对接步骤也相对应用内分享要多一点。

方案1:iOS 平台应用内分享

应用内分享的方案非常简单,只需要调用 TRTC SDK 提供的接口 startScreenCapture 并传入编码参数TRTCVideoEncParamTRTCVideoEncParam 参数可以设置为 null,此时 SDK 会沿用开始屏幕分享之前的编码参数。
我们推荐的用于 iOS 屏幕分享的编码参数是:
参数项
参数名称
常规推荐值
文字教学场景
分辨率
videoResolution
1280 × 720
1920 × 1080
帧率
videoFps
10 FPS
8 FPS
最高码率
videoBitrate
1600 kbps
2000 kbps
分辨率自适应
enableAdjustRes
NO
NO
说明:
由于屏幕分享的内容一般不会剧烈变动,所以设置较高的 FPS 并不经济,推荐10 FPS 即可。
如果您要分享的屏幕内容包含大量文字,可以适当提高分辨率和码率设置。
最高码率(videoBitrate)是指画面在剧烈变化时的最高输出码率,如果屏幕内容变化较少,实际编码码率会比较低。

方案2:iOS 平台跨应用分享

对接步骤

iOS 系统上的跨应用屏幕分享,需要增加 Extension 录屏进程以配合主 App 进程进行推流。Extension 录屏进程由系统在需要录屏的时候创建,并负责接收系统采集到屏幕图像。因此需要:
1. 创建 App Group,并在 XCode 中进行配置(可选)。这一步的目的是让 Extension 录屏进程可以同主 App 进程进行跨进程通信。
2. 在您的工程中,新建一个 Broadcast Upload Extension 的 Target,并在其中 Github 中专门为扩展模块定制的 TXLiteAVSDK_ReplayKitExt.framework
3. 对接主 App 端的接收逻辑,让主 App 等待来自 Broadcast Upload Extension 的录屏数据。
4. 编辑 pubspec.yaml 文件引入 replay_kit_launcher 插件 ,实现类似TRTC Demo Screen中点击一个按钮即可唤起屏幕分享的效果(可选)。
# 引入 trtc sdk和replay_kit_launcher
dependencies:
tencent_rtc_sdk: ^12.5.4
replay_kit_launcher: any
注意:
如果跳过 步骤1,也就是不配置 App Group(接口传 null),屏幕分享依然可以运行,但稳定性要打折扣,故虽然步骤较多,但请尽量配置正确的 App Group 以保障屏幕分享功能的稳定性。

步骤1:创建 App Group

使用您的账号登录 https://developer.apple.com/,进行以下操作,注意完成后需要重新下载对应的 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,如下图:

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

6. 选中主 App 的 Target ,并按照上述步骤对主 App 的 Target 做同样的处理。
7. 在新创建的 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 端的接收逻辑

按照如下步骤,对接主 App 端的接收逻辑。也就是在用户触发屏幕分享之前,要让主 App 处于“等待”状态,以便随时接收来自 Broadcast Upload Extension 进程的录屏数据。
1. 确保 TRTCCloud 已经关闭了摄像头采集,如果尚未关闭,请调用 stopLocalPreview 关闭摄像头采集。
2. 调用 startScreenCaptureByReplaykit 方法,并传入 步骤1 中设置的 AppGroup,让 SDK 进入“等待”状态。
3. 调用 replay_kit_launcher 提供的 launchReplayKitBroadcast 方法。
4. 等待用户触发屏幕分享。如果没有主动弹出iOS的屏幕录制提示框,则需要用户在 iOS 系统的控制中心,通过长按录屏按钮来触发,这一操作步骤如下图所示:

5. 通过调用 stopScreenCapture 接口可以随时中止屏幕分享。
_trtcCloud.startScreenCaptureByReplaykit(
TRTCVideoStreamType.sub,
TRTCVideoEncParam(
videoFps: 15,
videoResolution: TRTCVideoResolution.res_640_360,
videoBitrate: 1600,
minVideoBitrate: 0,
enableAdjustRes: false,
videoResolutionMode: TRTCVideoResolutionMode.landscape,
), "your app group");
ReplayKitLauncher.launchReplayKitBroadcast("screen capture");

基于 Windows 平台

Windows 平台下的屏幕分享支持主路分享和辅路分享两种方案:
辅路分享
在 TRTC 中,我们可以单独为屏幕分享开启一路上行的视频流,并称之为“辅路(substream)”。辅路分享即主播同时上行摄像头画面和屏幕画面两路画面。这是腾讯会议的使用方案,您可以在调用startScreenCapture接口时,通过将TRTCVideoStreamType参数指定为sub 来启用该模式。
主路分享
在 TRTC 中,我们一般把摄像头走的通道叫做“主路(bigstream)”,主路分享即用摄像头通道分享屏幕。该模式下,主播只有一路上行视频流,要么上行摄像头画面,要么上行屏幕画面,两者是互斥的。您可以在调用startScreenCapture接口时,通过将TRTCVideoStreamType参数指定为 big来启用该模式。

步骤1:获取分享目标

通过getScreenCaptureSources可以枚举可共享的窗口列表,列表通过出参 sourceInfoList 返回。

说明:
Windows 里的桌面屏幕也是一个窗口,叫桌面窗口(Desktop),有两台显示器时,每一台显示器都有一个对应的桌面窗口。所以,getScreenCaptureSources 返回的窗口列表里也会有 Desktop 窗口。
根据获取到的窗口信息,您可以实现一个简单的列表页面,将可以分享的目标罗列出来供用户选择。

步骤2:选择分享目标

当您通过 getScreenCaptureSources 获取到可以分享的屏幕和窗口之后,您可以调用 selectScreenCaptureTarget 接口选定期望分享的目标屏幕或目标窗口。

步骤3:开始屏幕分享

选取分享目标后,使用startScreenCapture 接口可以启动屏幕分享。
分享过程中,您依然可以通过调用selectScreenCaptureTarget更换分享目标。
pauseScreenCapturestopScreenCapture的区别在于 pause 会停止屏幕内容的采集,并以暂停那一刻的画面垫片,所以在远端看到一直都是最后一帧画面,直到 resume。

设定视频编码参数

通过设置 startScreenCapture() 中的首个参数 encParams ,您可以指定屏幕分享的编码质量,包括分辨率、码率和帧率,我们提供如下建议参考值:
清晰度级别
分辨率
帧率
码率
超高清(HD+)
1920 × 1080
10
800kbps
高清(HD)
1280 × 720
10
600kbps
标清(SD)
960 × 720
10
400kbps
如果您指定 encParams 为 null,SDK 会自动使用之前设定的编码参数。

观看屏幕分享

观看屏幕分享
若用户进行屏幕分享,且通过主流进行分享。房间里的其他用户会通过 TRTCCloudListener 中的 onUserVideoAvailable 事件获得这个通知。
希望观看屏幕分享的用户可以通过 startRemoteView 接口来启动渲染远端用户主流画面。

常见问题

一个房间里可以同时有多路屏幕分享吗?

目前一个 TRTC 音视频房间只能有一路屏幕分享。