屏幕共享
屏幕共享功能要求 RTCLib 版本大于等于 5.1.8。音视频通话场景暂不支持该功能,即集成 CallKit 或 CallLib 的应用中暂不支持此功能。
RTCLib SDK 支持屏幕共享。在音视频会议和直播时,可单独抓取屏幕视频数据,并将视频流数据发送到房间中。参与会议或直播的其他用户可以拉取该视频流,观看当前共享屏幕的内容。
屏幕共享主流程
- 共享屏幕的一方(发布端)通过
RCRTCEngine
的getScreenShareVideoStream()
方法获取屏幕共享流 RCRTCScreenShareOutputStream 的实例。RCRTCScreenShareOutputStream
为一个接口类,其中封装了操作屏幕共享的方法。 - 获取屏幕共享流对象后,调用
RCRTCScreenShareOutputStream
示例的startCaptureScreen
方法开始抓取屏幕。 - 根据当前的房间模式(直播默认或会议模式),选择合适的方法将抓取的屏幕共享视频流发布到房间中。
- 参与会议或直播的用户拉取屏幕共享流。注意,直播模式下房间中观众角色的用户一般订阅合流,而融云服务端会自动在合流中加入屏幕共享流,观众角色的用户无需单独订阅屏幕共享流。
如果 RTCLib SDK 版本为 5.1.15 及以上,可同时支持捕获第三方应用音频数据,并通过混音接口将捕获的音频数据发送到对端的,不需要额外发布音频流。具体操作参见下文第三方应用音频捕获。
前置条件
-
在 manifest 文件中粘贴如下 activity:
<activity android:name="cn.rongcloud.rtc.api.stream.RCRTCScreenShareActivity"></activity>
-
在 manifest 文件中粘贴如下 service:
<service
android:name="cn.rongcloud.rtc.api.stream.RCRTCScreenShareService"
android:enabled="true"
android:foregroundServiceType="mediaProjection" /> -
在 manifest 文件中添加如下前台服务权限:
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
步骤 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()); -
开启屏幕抓取。注意:请确保在调用
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();
-
(可选)本地可以对本端屏幕共享流进行预览。
// 用于本地预览的视图
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 支持在屏 幕共享时捕获第三方应用音频数据。
-
确保已发布本地麦克风采集的默认音频流,RTCLib 会通过混音接口将捕获的第三方音频数据混入默认音频流,通过默认音频流将混音结果发送到对端。
- 直播模式:publishDefaultLiveStreams,您也可以通过
RCRTCEngine.getInstance().getDefaultAudioStream()
获取默认音频流后再使用 publishLiveStream 方法自行发送。 - 会议模式:publishDefaultStreams,您也可以通过
RCRTCEngine.getInstance().getDefaultAudioStream()
获取默认音频流后再调用 publishStream 或 publishStreams 方法自行发送。
- 直播模式:publishDefaultLiveStreams,您也可以通过
-
确保第三方应用允许音频被其他应用捕获。调用
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。addMatchingUsage
与addMatchingUid
两个方法支持同时调用。 -
在调用
startCaptureAudio
前后,均可以控制捕获音频的音量,默认值 50,可选音量范围为 [1-100]。RCRTCEngine.getInstance().getScreenShareVideoStream().setCaptureAudioVolume(80);