跳到主要内容

屏幕共享

提示

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

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

屏幕共享主流程

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

若 RTCLib 版本 ≥ 5.1.15,可同时捕获第三方应用音频数据,并通过混音接口将捕获的音频数据发送到对端的,无需额外发布音频流。详见第三方应用音频捕获

前置条件

  1. AndroidManifest.xml 中添加如下 Activity:

    xml
    <activity android:name="cn.rongcloud.rtc.api.stream.RCRTCScreenShareActivity" />
  2. AndroidManifest.xml 中添加如下 Service:

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

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

步骤 1:开启屏幕抓取

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

    提示

    默认屏幕共享流分辨率为 720×960,帧率为 15 fps。

    Java
    RCRTCVideoStreamConfig.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());
  2. 开启屏幕抓取。请确保在调用 startCaptureScreen 前已完成融云音视频引擎初始化(RCRTCEngine.getInstance().init())。

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

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

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

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

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

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

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

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

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

    Java
    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() {
    // 发布成功
    }

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

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

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

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

    @Override
    public void onFailed(RTCErrorCode errorCode) {
    }
    });

步骤 3:拉取屏幕共享流

当房间中有用户成功发布了共享流时,其他用户会通过 IRCRTCRoomEventsListener#onRemoteUserPublishResource 收到通知,之后可拉取屏幕共享流。

提示

直播模式下,观众通常订阅合流。服务端会自动在合流中加入屏幕共享流,观众无需单独订阅屏幕共享流。

用户可以根据屏幕共享流的 tag 为 RongCloudScreenShare 来区分当前视频流是否为屏幕共享流,一次的来处理屏幕共享流相关逻辑。远端用户需要以拉取远端视频流的方法进行拉去该视频流,然后添加 videoView 进行渲染。

Java
/**
* 远端用户发布资源通知
*
* @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)) {
// 屏幕共享视频流
}
// 选择订阅大流或小流,默认小流
((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
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 支持在屏幕共享时捕获第三方应用音频数据。

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

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

    Java
    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。

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