观众端
直播模式中主播发布的音视频流,会在服务端另行合并生成一道音频合流和一道视频合流。观众既可以直接订阅原始音视频流(简称“分流”),也可订阅“合流”。下面将分别介绍这两种订阅方式的区别和适用场景。
观众被定义为只能订阅不能发布,如需发布必须先转为主播身份,再进行资源的发布。
订阅分流
分流订阅跟会议模式的订阅一样,适合小众玩法灵活的直播业务场景。比如观众被分成多种角色,需要选择性观看或收听部分主播发布的资源;又或者不同观众的展示布局并不相同,甚至可以随时切换布局的情况,SDK 提供视频展示 View 的创建和与流绑定接口,开发者自行编写展示逻辑。
观众的订阅需要在两个地方进行处理:一是在加入直播间的成功回调里,需要遍历得到房间内已经存在用户发布的流,并订阅;二是在收到主播刚刚发布流的通知,即 onRemoteUserPublishResource
时订阅。可调用 RCRTCLocalUser
中的 subscribeStream 或 subscribeStreams 来订阅单个或多个媒体流。
rtcRoom.getLocalUser().subscribeStreams(inputStreams, new IRCRTCResultDataCallback<List<RCRTCInputStream>>() {
@Override
public void onSuccess() {
}
@Override
// 如果 SDK ≧ 5.3.4,您可以使用 IRCRTCResultDataCallback,onFailed 方法会返回订阅失败的流列表和错误码。
// 如果 SDK < 5.3.4,仅支持使用 IRCRTCResultCallback,onFailed 方法仅返回错误码。
public void onFailed(List<RCRTCInputStream> failedStreams, RTCErrorCode errorCode) {
}
});
订阅合流
大部分直播场景,观众数量比较庞大,且所有观众看到和听到的内容完全一致。当有多个主播时,观众采用分流订阅的方式会造成大量带宽资源的浪费,客户成本也会较高。合流就是用来解决资源浪费问题的,它是由融云服务将所有主播发布的音视频资源,按客户提前指定的人选、布局方式和编码参数进行合并生成的一道音频和一道视频合流(纯音频模式仅有一道音频合流)。观众都去订阅这两道合流,则不管有多少名主播连麦/PK,观众都能用很少的资源得到一致的观看效果 ,从而为客户节省大量成本。下面介绍订阅合流的步骤:
-
获取合流地址:
当观众加入房间成功后,会在回调中拿到
RCRTCRoom
房间对象,此时如果主播已经发布了资源,调用其中的 getLiveStreams 就能拿到这些资源的合流地址列表,如果主播是在观众加入之后再发布的资源,可以通过IRCRTCRoomEventsListener
的 onPublishLiveStreams 回调方法获取合流地址列表,合流地址列表里面或为两道音视频流,或者一道音频流(纯音频模式)。//通过 getLiveStreams 方法获取
List<RCRTCInputStream> streamList = rtcRoom.getLiveStreams();
//通过 onPublishLiveStreams 方法获取
rtcRoom.registerRoomListener(new IRCRTCRoomEventsListener() {
....
@Override
public void onPublishLiveStreams(List<RCRTCInputStream> streams) {
//主播发布的合流资源列表
}
...
}); -
订阅合流:
拿到合流后,调用
RCRTCLocalUser
的 subscribeStream 或 subscribeStreams 即可订阅指定的一个或多个合流。用法与订阅分流一致,只不过传递的流对象不同,合流中的视频流是是区分大小流的,可以通过视频流RCRTCVideoInputStream
对象的 setStreamType 方法,来选择订阅大流(默认)或小流.List<RCRTCInputStream> inputStreams = rtcRoom.getLiveStreams();
// 获取当前房间所有已发布直播流,可能包括音频、视频、自定义等
for (RCRTCInputStream inputStream : inputStreams) {
// 需要渲染的只有视频流,单独筛出来加渲染逻辑
if (inputStream.getMediaType() == RCRTCMediaType.VIDEO){
RCRTCVideoInputStream videoInputStream = (RCRTCVideoInputStream) inputStream;
// 如果未绑定过 VideoView,则需要创建并绑定 VideoView
if (videoInputStream.getVideoView() == null) {
VideoView videoView = new VideoView(XXXActivity.this);
videoInputStream.setVideoView(videoView);
// 添加到 Activity 布局中,videoViewManager 是官网 Demo 中的一种方式,仅供参考
videoViewManager.add(videoView);
}
}
}
rtcRoom.getLocalUser().subscribeStreams(inputStreams, new IRCRTCResultDataCallback<List<RCRTCInputStream>>() {
@Override
public void onSuccess() {
}
@Override
// 如果 SDK ≧ 5.3.4,您可以使用 IRCRTCResultDataCallback,onFailed 方法会返回订阅失败的流列表和错误码。
// 如果 SDK < 5.3.4,仅支持使用 IRCRTCResultCallback,onFailed 方法仅返回错误码。
public void onFailed(List<RCRTCInputStream> failedStreams, RTCErrorCode errorCode) {
}
});
取消订阅
当需要取消订阅分流或合流时,可调用 RCRTCLocalUser
中的 unsubscribeStream 或 unsubscribeStreams 来取消订阅一道流或多道流。取消订阅接口通常跟订阅接口配对使用,但如果是用户想要退出房间,则不需要调用取消订阅方法,在调用退出房间接口时,SDK 内部会自动进行取消处理。
rtcRoom.getLocalUser().unsubscribeStreams(unPublishResource, new IRCRTCResultCallback() {
@Override
public void onSuccess() {
// 取消成功
}
@Override
public void onFailed(RTCErrorCode errorCode) {
// 取消失败
}
});
参数 | 类型 | 说明 |
---|---|---|
streams | List<? extends RCRTCInputStream> | 要取消订阅的音视频流 |
callBack | IRCRTCResultCallback | 取消订阅的音视频流的回调 |