屏幕共享
屏幕共享功能要求 RTCLib 版本 ≥ 5.1.8。音视频通话场景暂不支持该功能,即集成 CallKit 或 CallLib 的应用暂不支持。
RTCLib 支持屏幕共享。在音视频会议和直播时,可单独抓取屏幕视频数据,并将该视频流发送到房间中。参与会议或直播的其他用户可以拉取该视频流,观看当前共享屏幕的内容。
屏幕共享主流程
- 共享屏幕的一方(发布端)通过
RCRTCEngine的getScreenShareVideoStream()获取屏幕共享流 RCRTCScreenShareOutputStream 实例。该接口类封装了操作屏幕共享相关方法。 - 获取屏幕共享流对象后,调用
RCRTCScreenShareOutputStream实 例的startCaptureScreen方法开始抓取屏幕。 - 根据当前房间模式(会议或直播),选择合适的方法将抓取的屏幕共享视频流发布到房间中。
- 参与会议或直播的用户拉取屏幕共享流。注意:直播模式下,观众角色通常订阅合流,融云服务端会自动在合流中加入屏幕共享流,观众无需单独订阅屏幕共享流。
若 RTCLib 版本 ≥ 5.1.15,可同时捕获第三方应用音频数据,并通过混音接口将捕获的音频数据发送到对端的,无需额外发布音频流。详见第三方应用音频捕获。
前置条件
-
在
AndroidManifest.xml中添加如下 Activity:xml<activity android:name="cn.rongcloud.rtc.api.stream.RCRTCScreenShareActivity" /> -
在
AndroidManifest.xml中添加如下 Service:xml<service
android:name="cn.rongcloud.rtc.api.stream.RCRTCScreenShareService"
android:enabled="true"
android:foregroundServiceType="mediaProjection" /> -
在
AndroidManifest.xml中添加如下前台服务权限:xml<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
步骤 1:开启屏幕抓取
-
通过
RCRTCEngine.getInstance().getScreenShareVideoStream()获取用于屏幕共享的视频流,调用屏幕共享视频流对象的方法设置视频编码参数(帧率、分辨率、最大码率等)。提示默认屏幕共享流分辨率为 720×960,帧率为 15 fps。
JavaRCRTCVideoStreamConfig.Builder builder = Builder.create();
// 设置帧率
builder.setVideoFps(RCRTCVideoFps.Fps_15);
// 设置分辨率
builder.setVideoResolution(RCRTCVideoResolution.RESOLUTION_720_1280);
// 设置最大码率(kbps)
builder.setMaxRate(2500);
RCRTCEngine.getInstance().getScreenShareVideoStream().setVideoConfig(builder.build()); -
开启屏幕抓取。请确保在调用
startCaptureScreen前已完成融云音视频引擎初始化(RCRTCEngine.getInstance().init())。JavaRCRTCEngine.getInstance().getScreenShareVideoStream().startCaptureScreen(
new IRCRTCResultCallback() {
@Override
public void onSuccess() {
// 屏幕抓取开启成功
}
@Override
public void onFailed(RTCErrorCode errorCode) {
// 屏幕抓取开启失败
}
}
);当用户不需要屏幕抓取时,调用
stopCaptureScreen()关闭屏幕抓取。JavaRCRTCEngine.getInstance().getScreenShareVideoStream().stopCaptureScreen(); -
(可选)本地可以对本端屏幕共享流进行预览。
Java// 用于本地预览的视图
//SurfaceView 类型
RCRTCVideoView videoView = new RCRTCVideoView(getApplicationContext());
//5.34.0 版本开始支持 TextureView 类型
//RCRTCTextureView videoView = new RCRTCTextureView(getApplicationContext());
RCRTCEngine.getInstance().getScreenShareVideoStream().setVideoView(videoView);
步骤 2:发布屏幕共享视频流
使用 RCRTCLocalUser 提供的发布方法,可将本地用户的屏幕共享流发布到 RTC 房间中。也可以将屏幕共享流和其他音视频流一起发布到房间中。
加入房间(RCRTCEngine.getInstance().joinRoom())成功回调中可获取 RCRTCRoom 实例,并通过 getLocalUser() 方法获取本地用户 RCRTCLocalUser 实例。
-
会议模式:调用 publishStream 发布;当用户不需要进行屏幕共享时,可以通过 unpublishStream 取消屏幕共享。
JavaRCRTCEngine.getInstance().joinRoom("yourRoomId", new IRCRTCResultDataCallback<RCRTCRoom>() {
@Override
public void onSuccess(RCRTCRoom room) {
room.getLocalUser().publishStream(
RCRTCEngine.getInstance().getScreenShareVideoStream(),
new IRCRTCResultCallback() {
@Override
public void onSuccess() {
// 发布成功
}
@Override
public void onFailed(RTCErrorCode errorCode) {
// 发布失败
}
}
);
}
@Override
public void onFailed(RTCErrorCode errorCode) {
}
}); -
直播模式:调用 publishLiveStream 发布;当用户不需要进行屏幕共享时,可以通过 unpublishLiveStream 进行取消屏幕共享。
JavaRCRTCEngine.getInstance().joinRoom("yourRoomId", new IRCRTCResultDataCallback<RCRTCRoom>() {
@Override
public void onSuccess(RCRTCRoom room) {
room.getLocalUser().publishLiveStream(
RCRTCEngine.getInstance().getScreenShareVideoStream(),
new IRCRTCResultDataCallback<RCRTCLiveInfo>() {
@Override
public void onSuccess(RCRTCLiveInfo data) {
// 发布成功
}
@Override
public void onFailed(RTCErrorCode errorCode) {
// 发布失败
}
}
);
}
@Override
public void onFailed(RTCErrorCode errorCode) {
}
});
步骤 3:拉取屏幕共享流
当房间中有用户成功发布了共享流时,其他用户会通过 IRCRTCRoomEventsListener#onRemoteUserPublishResource 收到通知,之后可拉取屏幕共享流。
直播模式下,观众通常订阅合流。服务端会自动在合流中加入屏幕共享流,观众无需单独订阅屏幕共享流。
用户可以根据屏幕共享流的 tag 为 RongCloudScreenShare 来区分当前视频流是否为屏幕共享流,一次的来处理屏幕共享流相关逻辑。远端用户需要以拉取远端视频流的方法进行拉去该视频流,然后添加 videoView 进行渲染。
/**
* 远端用户发布资源通知
*
* @param remoteUser 远端用户
* @param streams 发布的资源
*/
@Override
public void onRemoteUserPublishResource(RCRTCRemoteUser remoteUser, List<RCRTCInputStream> streams) {
for (RCRTCInputStream inputStream : streams) {
if (inputStream.getMediaType() == RCRTCMediaType.VIDEO) {
if (inputStream.getTag().equals(RCRTCStream.TAG_SCREEN_SHARE)) {
// 屏幕共享视频流,创建用于预览的视图
//SurfaceView 类型
RCRTCVideoView videoView = new RCRTCVideoView(getApplicationContext());
//5.34.0 版本开始支持 TextureView 类型
//RCRTCTextureView videoView = new RCRTCTextureView(getApplicationContext());
((RCRTCVideoInputStream) inputStream).setVideoView(videoView);
//同时需要把 videoView 加入到用户的布局中
}
}
}
mRoom.getLocalUser().subscribeStreams(streams, new IRCRTCResultDataCallback<List<RCRTCInputStream>>() {
@Override
public void onSuccess() {
Log.d(TAG, "subscribeStreams:onSuccess");
}
@Override
public void onSuccess(List<RCRTCInputStream> data) {
}
@Override
// 若 SDK ≥ 5.3.4,可使用 IRCRTCResultDataCallback,onFailed 返回订阅失败的流列表与错误码;
// 若 SDK < 5.3.4,仅支持 IRCRTCResultCallback,onFailed 仅返回错误码。
public void onFailed(List<RCRTCInputStream> failedStreams, RTCErrorCode errorCode) {
Log.d(TAG, "subscribeStreams:onFailed: " + errorCode.getReason());
}
});
}
第三方应用音频捕获
RTCLib 5.1.15 及之后支持该功能,系统版本需为 Android 10 及以上。
RTCLib 支持在屏幕共享时捕获第三方应用音频数据。
-
确保已发布本地麦克风采集的默认音频流。RTCLib 会通过混音接口将捕获到的第三方音频数据混入默认音频流,通过默认音频流将混音结果发送到对端。
- 直播模式:publishDefaultLiveStreams。也可通过
RCRTCEngine.getInstance().getDefaultAudioStream()获取默认音频流后再使用 publishLiveStream 方法自行发送。 - 会议模式:publishDefaultStreams。也可通过
RCRTCEngine.getInstance().getDefaultAudioStream()获获取默认音频流后再调用 publishStream 或 publishStreams 方法自行发送。
- 直播模式:publishDefaultLiveStreams。也可通过
-
确保第三方应用允许音频被其他应用捕获。调用
addMatchingUsage添加要捕获的音频类型(该类型由被采集应用指定)。第三方应用开始播放音频后,调用startCaptureAudio开始捕获音频。RTCLib 会在您调用startCaptureAudio后捕获第三方应用的音频流,并通过混音接口将捕获的音频数据混入默认音频流,通过默认音频流将混音结果发送到对端。JavaRCRTCScreenShareAudioConfig audioConfig = RCRTCScreenShareAudioConfig.Builder.create()
.addMatchingUsage(RCRTCParamsType.RCRTCScreenShareAudioUsage.MEDIA)
.addMatchingUsage(RCRTCParamsType.RCRTCScreenShareAudioUsage.GAME)
.addMatchingUsage(RCRTCParamsType.RCRTCScreenShareAudioUsage.UNKNOWN)
.build();
RCRTCEngine.getInstance().getScreenShareVideoStream().startCaptureAudio(audioConfig, new IRCRTCResultCallback() {
@Override
public void onSuccess() {
}
@Override
public void onFailed(RTCErrorCode errorCode) {
}
});也可调用
addMatchingUid指定被捕获应用的 UID。addMatchingUsage与addMatchingUid两个方法支持同时调用。 -
在调用
startCaptureAudio前后均可设置捕获音频的音量。默认 50,取值范围 1 ~ 100。JavaRCRTCEngine.getInstance().getScreenShareVideoStream().setCaptureAudioVolume(80);