跳到主要内容

屏幕共享

提示

屏幕共享功能要求 RTCLib 版本大于等于 5.1.8。音视频通话场景暂不支持该功能,即集成 CallKit 或 CallLib 的应用中暂不支持此功能。

RTCLib SDK 支持屏幕共享。在音视频会议和直播时,可单独抓取屏幕视频数据,并将视频流数据发送到房间中。参与会议或直播的其他用户可以拉取该视频流,观看当前共享屏幕的内容。

屏幕共享主流程

  1. 共享屏幕的一方(发布端)通过 RCRTCEnginegetScreenShareVideoStream() 方法获取屏幕共享流 RCRTCScreenShareOutputStream 的实例。RCRTCScreenShareOutputStream 为一个接口类,其中封装了操作屏幕共享的方法。
  2. 获取屏幕共享流对象后,调用 RCRTCScreenShareOutputStream 示例的 startCaptureScreen 方法开始抓取屏幕。
  3. 根据当前的房间模式(直播默认或会议模式),选择合适的方法将抓取的屏幕共享视频流发布到房间中。
  4. 参与会议或直播的用户拉取屏幕共享流。注意,直播模式下房间中观众角色的用户一般订阅合流,而融云服务端会自动在合流中加入屏幕共享流,观众角色的用户无需单独订阅屏幕共享流。

如果 RTCLib SDK 版本为 5.1.15 及以上,可同时支持捕获第三方应用音频数据,并通过混音接口将捕获的音频数据发送到对端的,不需要额外发布音频流。具体操作参见下文第三方应用音频捕获

前置条件

  1. 在 manifest 文件中粘贴如下 activity:

    <activity android:name="cn.rongcloud.rtc.api.stream.RCRTCScreenShareActivity"></activity>
  2. 在 manifest 文件中粘贴如下 service:

    <service
    android:name="cn.rongcloud.rtc.api.stream.RCRTCScreenShareService"
    android:enabled="true"
    android:foregroundServiceType="mediaProjection" />
  3. 在 manifest 文件中添加如下前台服务权限:

    <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />

步骤 1:开启屏幕抓取

  1. 通过 RCRTCEngine.getInstance().getScreenShareVideoStream() 获取用于屏幕共享的视频流,调用屏幕共享视频流对象的方法设置视频编码参数,包括帧率、分辨率、和最大码率等。

    提示

    默认屏幕共享流的分辨率为:720x960,帧率为:15fps

    RCRTCVideoStreamConfig.Builder builder = Builder.create();
    // 设置帧率
    builder.setVideoFps(RCRTCVideoFps.Fps_15);
    // 设置分辨率
    builder.setVideoResolution(RCRTCVideoResolution.RESOLUTION_720_1280);
    // 设置最大码率
    builder.setMaxRate(2500);
    RCRTCEngine.getInstance().getScreenShareVideoStream().setVideoConfig(builder.build());
  2. 开启屏幕抓取。注意:请确保在调用 startCaptureScreen 之前已经完成融云音视频引擎初始化(RCRTCEngine.getInstance().init())。

    RCRTCEngine.getInstance().getScreenShareVideoStream().startCaptureScreen(
    new IRCRTCResultCallback() {
    @Override
    public void onSuccess() {
    //todo 屏幕抓取开启成功
    }

    @Override
    public void onFailed(RTCErrorCode errorCode) {
    //todo 屏幕抓取开启失败
    }
    });

    当用户不需要屏幕抓取时,需要调用 stopCaptureScreen() 关闭屏幕抓取。

    RCRTCEngine.getInstance().getScreenShareVideoStream().stopCaptureScreen();
  3. (可选)本地可以对本端屏幕共享流进行预览。

    // 用于本地预览的视图
    RCRTCVideoView videoView = new RCRTCVideoView(getApplicationContext());
    RCRTCEngine.getInstance().getScreenShareVideoStream().setVideoView(videoView);

步骤 2:发布屏幕共享视频流

使用 RCRTCLocalUser 实例提供的发布方法,可以将本地用户的屏幕共享流发布到 RTC 房间中。您也可以将屏幕共享流和其他音视频流一起发布到房间中。

您可以在加入房间(RCRTCEngine.getInstance().joinRoom())的成功回调中可获取 RTC 房间 RCRTCRoom 实例,并使用 RCRTCRoom 实例 getLocalUser() 方法获取本地用户 RCRTCLocalUser 实例。

  • 会议模式下需要调用 publishStream 方法。当用户不需要进行屏幕共享时,可以通过 unpublishStream 取消屏幕共享。

    RCRTCEngine.getInstance().joinRoom("yourRoomId", new IRCRTCResultDataCallback<RCRTCRoom>() {
    @Override
    public void onSuccess(RCRTCRoom room) {
    room.getLocalUser().publishStream(
    RCRTCEngine.getInstance().getScreenShareVideoStream(),
    new IRCRTCResultCallback() {
    @Override
    public void onSuccess() {
    //todo 发布成功
    }

    @Override
    public void onFailed(RTCErrorCode errorCode) {
    //todo 发布失败
    }
    });
    }

    @Override
    public void onFailed(RTCErrorCode errorCode) {
    }
    });
  • 直播模式下需要调用 publishLiveStream 方法。当用户不需要进行屏幕共享时,可以通过 unpublishLiveStream 进行取消屏幕共享。

    RCRTCEngine.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) {
    //todo 发布成功
    }

    @Override
    public void onFailed(RTCErrorCode errorCode) {
    //todo 发布失败
    }
    });
    }

    @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)){
//todo 屏幕共享视频流
}
// 选择订阅大流或是小流。默认小流
((RCRTCVideoInputStream) inputStream).setStreamType(RCRTCStreamType.NORMAL);
// 创建VideoView并设置到stream
VideoViewWrapper videoViewWrapper =
createVideoViewByStreamId(inputStream.getStreamId(),
remoteUser.getUserId());
((RCRTCVideoInputStream) inputStream).setVideoView(videoViewWrapper.getRCRTCVideoView());
// 将远端视图添加至布局
addVideoViewToList(videoViewWrapper);
onShowVideoViewChange(mVideoViewList);
}
}
mRoom.getLocalUser().subscribeStreams(streams, new IRCRTCResultDataCallback<List<RCRTCInputStream>>() {
@Override
public void onSuccess() {
Log.d(TAG, "subscribeStreams:onSuccess: ");
}

@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: " + rtcErrorCode.getReason());
}
});
}

第三方应用音频捕获

提示

RTCLib 5.1.15 及之后支持该功能。要求系统版本 Android 10 及以上。

RTCLib 支持在屏幕共享时捕获第三方应用音频数据。

  1. 确保已发布本地麦克风采集的默认音频流,RTCLib 会通过混音接口将捕获的第三方音频数据混入默认音频流,通过默认音频流将混音结果发送到对端。

  2. 确保第三方应用允许音频被其他应用捕获。调用 addMatchingUsage 方法,添加捕获的音频类型,该类型由被采集应用自身指定。在第三方应用开始播放音频之后,调用 startCaptureAudio 方法开始捕获音频。RTCLib 会在您调用 startCaptureAudio 后捕获第三方应用的音频流,并通过混音接口将捕获的音频数据混入默认音频流,通过默认音频流将混音结果发送到对端。

    RCRTCScreenShareAudioConfig 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。addMatchingUsageaddMatchingUid 两个方法支持同时调用。

  3. 在调用 startCaptureAudio 前后,均可以控制捕获音频的音量,默认值 50,可选音量范围为 [1-100]。

    RCRTCEngine.getInstance().getScreenShareVideoStream().setCaptureAudioVolume(80);