融云 CDN 插件
融云 CDN 插件(RongRTCPlayer
)直接在 RTC 房间内提供了 融云 CDN 服务的订阅、播放等处理逻辑,降低了 App 业务侧的接入成本。
融云 CDN 插件(RongRTCPlayer
) 从 5.3.0 版本开始提供 CDN 播放器组件 RCRTCMediaPlayer
,可直接通过 CDN 地址播放 CDN 流、获取 SEI 数据、或直接获取音视频帧数据用于自行处理。详见 CDN 播放器。
本文主要描述如何通过融云 CDN 插件(RongRTCPlayer
)操作和使用 RTC 房间内的 CDN 资源。
集成融云 CDN 插件
融云 CDN 插件(RongRTCPlayer
) 集成方式详见导入 SDK。如果通过 Android 本地库模块 (Module) 导入,请将 aar 文件拷贝到 App 工程目录下。
推流到融云 CDN 服务
您可以通过融云 CDN 服务的配置,由融云服务端控制,将 RTC 房间的直播流转推到融云 CDN。融云 CDN 服务获取直播流后,RTC 房间内将会新增 CDN 流资源,观众可以直接订阅。App 需要根据业务要求指定推流时机:
- 开播自动推流:所有直播房间的直播流都会自动推流到融云 CDN。观众可随时订阅。
- 开播手动推流:App 需要在直播主播开始推流后,通过客户端接口
enableInnerCDN
控制是否推流到融云 CDN 服务。
如果推拉流模式为自行生成推拉流地址,融云服务端不负责将 RTC 房间的直播流转推到融云 CDN。您按照融云 CDN 服务的地址规则生成地址后,可通过客户端或服务端的旁路推流 API 将直播流传入融云 CDN 服务。
手动推流到融云 CDN
如果控制台推拉流模式为开播手动推流,必须在 App 客户端自行决定是否推流到融云 CDN 服务。在整个直播过程中都可以操作开关。
主播在 RTC 房间中发布资源后(详见发布与取消),通过回调中返回的 RCRTCLiveInfo 对象操作是否启用向融云 CDN 推流。
以发布默认音视频流为例:
// 直播模式下,发布默认音视频流,即麦克风、摄像头采集数据
room.getLocalUser().publishDefaultLiveStreams(new IRCRTCResultDataCallback<RCRTCLiveInfo>() {
@Override
public void onSuccess(RCRTCLiveInfo liveInfo) {
// 发布成功
}
@Override
public void onFailed(RTCErrorCode code) {
// 发布失败
}
});
RCRTCLiveInfo 对象提供以下方法设置是否向融云 CDN 服务推流:
void enableInnerCDN(boolean enable, IRCRTCResultCallback callBack);
参数 | 类型 | 说明 |
---|---|---|
enable | boolean | 是否开启 |
callBack | IRCRTCResultCallback | 完成回调 |
liveInfo.enableInnerCDN(enable, new IRCRTCResultCallback() {
@Override
public void onSuccess() {
}
@Override
public void onFailed(RTCErrorCode rtcErrorCode) {
}
});
开启或关闭内置 CDN 时,观众均会收到对应回调。
-
开启内置 CDN 时:房间中的观众会收到 IRCRTCRoomEventsListener 中
onPublishCDNStream(RCRTCCDNInputStream stream)
回调。 -
关闭内置 CDN 时:房间中观众会收到 IRCRTCRoomEventsListener 中
onUnpublishCDNStream(RCRTCCDNInputStream stream)
回调。
获取房间内 CDN 资源
采用开播自动推流或开播手动推流方式将直播流推到融云 CDN 服务后,RTC 房间内的观众可获取房间内的 CDN 资源。
观众可通过以下方式获取房间内 CDN 资源:
-
加入房间时获取:观众使用加入房间时,如果房间中已经存在 RCRTCCDNInputStream 流,可使用加入房间成功后获取到的 RCRTCRoom 对象的 getCDNStream 方法获取。
-
通过房间事件监听获取:观众加入房间成功后,可通过
RCRTCRoom
注册房间事件监听 IRCRTCRoomEventsListener 获取本房间中RCRTCCDNInputStream
流的发布和取消发布回调事件。rcrtcRoom.registerRoomListener(new IRCRTCRoomEventsListener() {
/**
* Added from 5.1.5
*
* 直播 CDN 流资源发布
*/
@Override
public void onPublishCDNStream(RCRTCCDNInputStream stream) {
super.onPublishCDNStream(stream);
}
/**
* Added from 5.1.5
*
* 直播 CDN 流资源取消发布
*/
@Override
public void onUnpublishCDNStream(RCRTCCDNInputStream stream) {
super.onUnpublishCDNStream(stream);
}
});
订阅房间内 CDN 资源
观众可以调用 RCRTCLocalUser 类的 subscribeStreams
方法订阅房间中 RCRTCCDNInputStream 资源。默认订阅 RCRTCCDNInputStream
的原始分辨率、帧率,即 getHighestResolution 和 getHighestFPS。
void subscribeStreams(List<? extends RCRTCInputStream> streams, IRCRTCResultDataCallback callBack);
参数 | 类型 | 说明 |
---|---|---|
streams | List<? extends RCRTCInputStream> | 音视频流集合 |
callBack | IRCRTCResultCallback | 订阅结果回调 |
在 streams
中传入房间内的 CDN 流资源。
RCRTCCDNInputStream inputStream = mRtcRoom.getCDNStream();
if (mRtcRoom == null || inputStream == null) {
// 没有加入房间 或 房间中没有 RCRTCCDNInputStream 流
return;
}
RCRTCVideoView videoView = new RCRTCVideoView(this);
// 设置视频流的渲染视图
inputStream.setVideoView(videoView);
// 显示流渲染视图
frameLayout.addView(videoView);
List<RCRTCInputStream> inputStreams = new ArrayList<>();
inputStreams.add(inputStream);
mRtcRoom.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 类的 unsubscribeStreams()
方法取消订阅 RCRTCCDNInputStream
资源。
void unsubscribeStreams(List<? extends RCRTCInputStream> streams, IRCRTCResultCallback callBack);
参数 | 类型 | 说明 |
---|---|---|
streams | List<? extends RCRTCInputStream> | 取消订阅的音视频流集合,RCRTCInputStream |
callBack | IRCRTCResultCallback | 取消订阅的结果回调 |
RCRTCCDNInputStream inputStream = mRtcRoom.getCDNStream();
if (inputStream == null) {
// 房间中没有 RCRTCCDNInputStream 流,可能是主播没有发布
return;
}
List<RCRTCInputStream> inputStreams = new ArrayList<>();
inputStreams.add(inputStream);
mRtcRoom.getLocalUser().unsubscribeStreams(inputStreams, new IRCRTCResultCallback() {
@Override
public void onSuccess() {
}
@Override
public void onFailed(final RTCErrorCode rtcErrorCode) {
}
});
调整订阅分辨率
观众可 以在订阅房间内 CDN 资源前后调整分辨率和帧率。
- 观众订阅房间内 默认订阅
RCRTCCDNInputStream
的原始分辨率、帧率,即 getHighestResolution 和 getHighestFPS。 - 调整分辨率和帧率会触发 CDN 转码服务,转码对计费有影响。详见音视频直播增值服务计费说明。
调用订阅方法前,订阅成功后,均可以通过 RCRTCCDNInputStream#setVideoConfig(RCRTCVideoResolution videoResolution, RCRTCVideoFps videoFps, IRCRTCResultCallback callback)
设置本次订阅资源的分辨率、帧率。
/**
* 该方法有两个功能如下:
* 1. 当没有订阅 RCRTCCDNInputStream 流时,订阅前指定的分辨率、帧率。
* 2. 已经订阅 RCRTCCDNInputStream 时调用,切换已经订阅 RCRTCCDNInputStream 的分辨率、帧率。
*
* @param videoResolution 默认为null。为null时默认订阅原始 CDN 流分辨率
* @param videoFps 默认为null。为null时默认订阅原始 CDN 流帧率
*/
setVideoConfig(RCRTCVideoResolution videoResolution, RCRTCVideoFps videoFps, IRCRTCResultCallback callback)
参数 | 类型 | 说明 |
---|---|---|
videoResolution | RCRTCVideoResolution | 分辨率枚举 |
videoFps | RCRTCVideoFps | 帧率枚举 |
callBack | IRCRTCResultCallback | 结果回调 |
RCRTCVideoResolution videoResolution = RCRTCVideoResolution.RESOLUTION_720_1280;
RCRTCVideoFps videoFps = RCRTCVideoFps.Fps_15;
mRoom.getCDNStream().setVideoConfig(videoResolution, videoFps, new IRCRTCResultCallback() {
@Override
public void onSuccess() {
}
@Override
public void onFailed(RTCErrorCode errorCode) {
}
});
观众端禁用 CDN 流渲染
观众成功订阅 RTC 房间内的 CDN 流后,可调用 CDN 流 RCRTCCDNInputStream
的 mute(boolean mute);
方法禁用或启用 CDN 流渲染。
void mute(boolean mute);
参数 | 类型 | 说明 |
---|---|---|
mute | boolean | true:停止资源渲染,false:恢复资源渲染 |
RCRTCCDNInputStream stream = mRoom.getCDNStream();
if (stream != null) {
stream.mute(true);
}
监听房间内 CDN 流的 SEI
SDK 从 5.3.0 版本开始支持监听和接收房间内 CDN 流的 SEI 数据。
在观众订阅 RTC 房间内的 CDN 流( RCRTCCDNInputStream
)前,给 RCRTCCDNInputStream
注册 RCRTCVideoCDNInputStreamEventListener
,可通过 onReceiveSEI
回调方法获取房间内 CDN 流的 SEI 数据。
RCRTCCDNInputStream rcrtccdnInputStream =
RCRTCEngine.getInstance().getRoom().getCDNStream();
if (rcrtccdnInputStream != null) {
rcrtccdnInputStream.setStreamEventListener(
new RCRTCVideoCDNInputStreamEventListener() {
//获取CDN流中的 sei 数据
@Override
public void onReceiveSEI(String sei) {
Log.d(TAG, "onReceiveSEI:" + sei);
}
@Override
public void onFrameSizeChanged(
RCRTCVideoInputStream stream, int width, int height) {
}
@Override
public void onFrameRotationChanged(
RCRTCVideoInputStream stream, int rotation) {
}
@Override
public RCRTCVideoFrame onRenderFrame(
RCRTCVideoInputStream stream, RCRTCVideoFrame frame) {
return frame;
}
});
}