文档导航
Android
SDK 版本:  5.X

屏幕共享

更新时间:2024-02-08 PDF
提示

屏幕共享功能要求 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>
                  
    已复制
    1

  2. 在 manifest 文件中粘贴如下 service:

    <service
        android:name="cn.rongcloud.rtc.api.stream.RCRTCScreenShareService"
        android:enabled="true"
        android:foregroundServiceType="mediaProjection" />
                  
    已复制
    1
    2
    3
    4

  3. 在 manifest 文件中添加如下前台服务权限:

    <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
                  
    已复制
    1

步骤 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());
                  
    已复制
    1
    2
    3
    4
    5
    6
    7
    8

  2. 开启屏幕抓取。注意:请确保在调用 startCaptureScreen 之前已经完成融云音视频引擎初始化(RCRTCEngine.getInstance().init())。

    RCRTCEngine.getInstance().getScreenShareVideoStream().startCaptureScreen(
    new IRCRTCResultCallback() {
        @Override
        public void onSuccess() {
            //todo 屏幕抓取开启成功
        }
    
        @Override
        public void onFailed(RTCErrorCode errorCode) {
            //todo 屏幕抓取开启失败
        }
    });
                  
    已复制
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12

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

    RCRTCEngine.getInstance().getScreenShareVideoStream().stopCaptureScreen();
                  
    已复制
    1

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

    // 用于本地预览的视图
    RCRTCVideoView videoView = new RCRTCVideoView(getApplicationContext());
    RCRTCEngine.getInstance().getScreenShareVideoStream().setVideoView(videoView);
                  
    已复制
    1
    2
    3

步骤 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) {
                }
            });
                  
    已复制
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22

  • 直播模式下需要调用 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) {
                }
            });
                  
    已复制
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22

步骤 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());
            }
        });
    }
              
已复制
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

第三方应用音频捕获

提示

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) {
        }
    });
                  
    已复制
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14

    您也可以通过调用 addMatchingUid 指定的捕获应用的 Uid。addMatchingUsageaddMatchingUid 两个方法支持同时调用。

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

    RCRTCEngine.getInstance().getScreenShareVideoStream().setCaptureAudioVolume(80);
                  
    已复制
    1

文档反馈
意见反馈

您的改进建议

意见反馈

问题类型

联系我们

提交工单

技术支持|集成使用|产品方案


商务咨询

7 x 24 小时

为您解答方案与报价问题

131 6185 6839

文档反馈