CDN推流
更新时间: 2024/03/15 17:25:07
NERTC SDK 融合了 CDN 推流能力,您只要集成一个 SDK 即可实现单人直播、PK 直播和连麦,且三个场景之间能无缝切换,提升 PK 直播体验。
flowchart LR
A("创建应用并获取 App Key") --> B(开通音视频通话 2.0 和直播服务)--> E("获取推拉流地址")--> C("集成 RTC SDK") --> D(实现 CDN 推流)
click A "https://doc.yunxin.163.com/console/docs/TIzMDE4NTA?platform=console"
click B "https://doc.yunxin.163.com/nertc/guide/jY3MzMwODA?platform=android"
click C "https://doc.yunxin.163.com/nertc/guide/DcyNDc0ODI?platform=android"
click E "https://doc.yunxin.163.com/live-streaming/docs/DM4MjYxODY?platform=android#步骤3-获取推拉流地址"
style D fill:#337EFF,stroke:#337EFF,stroke-width:0px,color:#FFFFFF;
style A fill:#9DC3E6,stroke:#9DC3E6,stroke-width:0px,color:#FFFFFF;
style B fill:#9DC3E6,stroke:#9DC3E6,stroke-width:0px,color:#FFFFFF;
style C fill:#9DC3E6,stroke:#9DC3E6,stroke-width:0px,color:#FFFFFF;
style E fill:#9DC3E6,stroke:#9DC3E6,stroke-width:0px,color:#FFFFFF;
功能描述
- 在单人直播时,SDK 将主播的音视频直接推流到 CDN 分发,观众端无需加入 RTC 房间即可通过播放器拉流观看。
- 在 PK 直播时,通过跨频道转发,主播无须切换 SDK,也不需要退出或重新进入房间,直接将媒体流转发到主播房间和挑战者房间,实现主播跨房间与其他主播实时互动。直播间内的观众可以同时观看两个主播 PK 互动,场景无缝切换,不会出现黑屏卡顿问题。
- 只有指定版本的 NERTC SDK 支持 CDN 推流功能。请在 SDK 下载中心的直播推流区域下载对应的 SDK。
- 为了保障您的直播体验,接入之前,请联系网易云信技术支持根据您的场景为您提供专属的 1 对 1 服务。
应用场景
该功能适用于直播间PK、游戏、在线教育等场景。
- 秀场直播:PK 连麦是视频互动直播的主流玩法,多个主播间通过主动邀请、随机匹配等方式互相配对,连麦成功后通过斗歌等方式进行 PK 竞技,并在一定时限内决出胜负,获胜一方可获得奖励,例如粉丝礼物、打赏、积分等。
- 游戏场景:用户可以选择与其他玩家进行 PK,通过 PK 功能实现双方的音视频流同步播放,提高游戏体验。
- 电商直播:可通过引入 PK 连麦模式,实现价格比拼等直播形式,激起用户的购买欲望,摆脱传统电商直播缺少互动的单调形式。
- 在线教育:老师和学生可以通过 PK 功能进行互动课堂,实现音视频流的同步播放,提高学习效果。
前提条件
完整示例代码
网易云信为您提供实现 CDN 推流的示例代码作为参考,您可以直接拷贝用于运行测试。
请单击下载CDN 推流最佳实践代码。
功能原理
单人直播
单人直播的架构原理如下图所示。
单人直播模式下,主播 A 和主播 B 分别加入房间 A 和 B,NERTC SDK 将主播音视频直接推流到 CDN 分发,观众端使用 RTMP/HLS/FLV 协议进行拉流观看。
PK 直播
PK 直播的架构原理如下图所示。
PK 直播的业务流程说明如下:
- 主播 A 发出 PK 邀请,主播 B 同意。
- 通过跨频道转发,主播 A 和主播 B 不需要退出原房间,直接将媒体流转发到房间 A 和房间 B 中,实现主播跨房间与其他主播实时互动。
- 互动直播服务器将主播 A 和主播 B 的音视频进行混屏转码后,推到 CDN 分发。
- 观众端使用 RTMP/HLS/FLV 协议进行拉流观看。
连麦
连麦的架构原理如下图所示。
连麦的业务流程说明如下:
- 观众申请上麦,主播同意上麦申请后,观众加入 RTC 房间。
- 互动直播服务器将主播和观众的音视频进行混屏转码后,推到 CDN 分发。
- 观众端使用 RTMP/HLS/FLV 协议进行拉流观看。
注意事项
- 只支持网易云信播放器 NELivePlayer 进行拉流,其他播放器暂不兼容。
- 单人直播切换到 PK 直播时,音频采样率必须保持一致。
- 旁路推流时请使用客户端的推流接口(
addLiveStreamTask
),不要使用服务端的旁路推流接口,因为客户端推流接口针对本场景做了适配处理。
集成 RTC SDK
只有指定版本的 NERTC SDK 支持 CDN 推流功能,请参考如下方法集成对应版本的 NERTC SDK。详细的集成 SDK 的步骤请参见集成 SDK。
使用 maven 集成指定版本 SDK 的示例代码如下:
implementation 'com.netease.yunxin:nertc:4.6.422'
如需手动集成,请到 SDK 下载中心的直播推流区域下载最新版本的 SDK。
导入类
在您的工程中对应实现音视频通话的 Activity 文件里添加如下代码先导入以下重要类:
javaimport com.netease.lava.nertc.sdk.NERtcCallbackEx;
import com.netease.lava.nertc.sdk.NERtcConstants;
import com.netease.lava.nertc.sdk.NERtcEx;
import com.netease.lava.nertc.sdk.NERtcParameters;
import com.netease.lava.nertc.sdk.video.NERtcRemoteVideoStreamType;
import com.netease.lava.nertc.sdk.video.NERtcVideoView;
实现单人直播
API 时序图
sequenceDiagram
actor 主播A
participant NERtcSDK
主播A->>NERtcSDK: init 初始化引擎
主播A->>NERtcSDK: enableLocalVideo(true) 开启视频的采集和发送
主播A->>NERtcSDK: enableLocalAudio(true)
主播A->>NERtcSDK: setAudioProfile 设置音频属性
主播A->>NERtcSDK: setLocalVideoConfig 设置视频属性
主播A->>NERtcSDK: setChannelProfile 设置场景属性为直播
rect rgb(191, 223, 255)
主播A->>NERtcSDK: startPushStreaming 开始推流
NERtcSDK-->>主播A: onStartPushStreaming
主播A->>NERtcSDK: stopPushStreaming 停止推流
NERtcSDK-->>主播A: onStopPushStreaming
end
实现方法
-
初始化引擎。
调用
init
方法完成初始化。您还需要在初始化时注册相关必要回调,建议您请在初始化方法中传入原型为 NERtcCallbackEx 的回调,并增加相应必要的处理。直播推流相关回调请参见常用的回调。
-
设置本地视频画布。 初始化成功后,可以设置本地视图,来预览本地图像。您可以根据业务需要实现加入房间之前预览或加入房间后预览。
- 若您想设置画布渲染参数,可以调用
setScalingType
方法设置渲染缩放模式或调用setMirror
方法设置镜像模式。 - 若您想调整摄像头的相关参数,请参考视频设备管理进行设置。
- 在加入房间前,默认预览分辨率为 640*480,您可以通过
setLocalVideoConfig
接口的width
和height
参数调整采集分辨率。
- 实现加入房间前预览。
-
调用
setupLocalVideoCanvas
与startVideoPreview(streamType)
方法,在加入房间前设置本地视图,预览本地图像。 -
若要结束预览,或者准备加入房间时,调用
stopVideoPreview(streamType)
方法停止预览。stopVideoPreview(streamType)
的streamType
参数请与startVideoPreview(streamType)
的保持一致,即同为主流或辅流的开启和停止预览。
-
实现加入房间后预览。
调用
setupLocalVideoCanvas
设置本地视图,再调用enableLocalVideo(streamType)
方法进行视频的采集发送与预览。成功加入房间后,即可预览本地图像。
- 若您想设置画布渲染参数,可以调用
-
调用
enableLocalVideo(streamType)
和enableLocalAudio
方法进行视频和音频的采集发送。 -
开始直播前,调用
setChannelProfile
接口,设置房间的场景属性为直播场景(kNERtcChannelProfileLiveBroadcasting
)。 -
直播前或直播中,调用
setAudioProfile
和setLocalVideoConfig
接口,分别设置音频属性和视频属性。 本场景中相关参数的推荐配置如下表所示。
属性 |
推荐配置 |
推荐原因 |
---|---|---|
音频属性 |
|
高清音质。满足娱乐场景中主播对高音质的需求。 |
以整体画布比例为 16:9 为例:
|
保证画质清晰度。 |
-
主播调用
startPushStreaming
接口,将房间中的音视频流推流到 CDN 上,NERtcPushStreamingConfig
相关参数说明如下表所示。参数 描述 streamingUrl 指定该音视频流的 CDN 推流地址。推流地址的获取方法请参见获取推拉流地址。 + NERtcStreamingRoomInfo 推流的房间信息。 -
推流成功后,房间内的用户会收到
onStartPushStreaming
的回调。 -
直播结束后,调用
stopPushStreaming
接口停止推流。 -
停止推流后,房间内的用户会收到
onStopPushStreaming
回调。
示例代码
实现单人直播主流程的示例代码如下:
public int startLive(NERtcPushStreamingConfig config) {
//step1 基础设置
//初始化引擎(具体初始化方法参见初始化接口init相关)
NERtcEx.getInstance().init(context, appkey, callback, option);
////打开音视频
NERtcEx.getInstance().enableLocalVideo(true);
NERtcEx.getInstance().enableLocalAudio(true);
//以下设置为了保证直播效果,建议开启
//建议audioprofile设置为kNERtcAudioProfileHighQuality和kNERtcAudioScenarioMusic
NERtcEx.getInstance().setAudioProfile(NERtcConstants.AudioProfile.HIGH_QUALITY, NERtcConstants.AudioScenario.MUSIC);
//建议设置为直播模式
NERtcEx.getInstance().setChannelProfile(NERtcConstants.RTCChannelProfile.LIVE_BROADCASTING);
//其他设置
//step2 调用开始推流接口
//(如果接口未返回错误, 监听onStartPushStreaming回调处理推流结果;如果接口报错,直接处理相关错误)
return NERtcEx.getInstance().startPushStreaming(config);
}
实现加入房间前预览的示例代码如下:
java//以开启本地视频主流预览为例
NERtcVideoView localView = (NERtcVideoView)findViewById(R.id.render_view_local);
NERtcEx.getInstance().setupLocalVideoCanvas(localView);
NERtcEx.getInstance().startVideoPreview(kNERtcVideoStreamTypeMain);
//设置本地视频画面的渲染模式:以保证原始视频尺寸比例为例(可选)
NERtcEx.getInstance().setScalingType(NERtcConstants.VideoScalingType.SCALE_ASPECT_FIT);
//设置本地视频画面的镜像模式:以开启镜像为例(可选)
NERtcEx.getInstance().setMirror(true);
实现加入房间后预览的示例代码如下:
java//设置本地预览画布
NERtcVideoView localView = (NERtcVideoView)findViewById(R.id.render_view_local);
NERtcEx.getInstance().setupLocalVideoCanvas(localView);
//以开启本地视频主流采集并发送为例
NERtcEx.getInstance().enableLocalVideo(true,kNERtcVideoStreamTypeMain);
//设置本地视频画面的渲染模式:以保证原始视频尺寸比例为例(可选)
NERtcEx.getInstance().setScalingType(NERtcConstants.VideoScalingType.SCALE_ASPECT_FIT);
//设置本地视频画面的镜像模式:以开启镜像为例(可选)
NERtcEx.getInstance().setMirror(true);
实现 PK 直播
下文介绍在单人直播的过程中,主播 A 邀请主播 B 进行PK直播实现流程。
API 时序图
sequenceDiagram
actor 主播A
participant NERtcSDK
participant 业务服务器
actor 主播B
%% 开始PK
主播A->>业务服务器: 邀请PK
Note right of 主播A: 邀请主播B进行PK(带上自己的uid、cname、Token等信息)
Note left of 主播B: 请自行实现邀请PK的相关业务逻辑
业务服务器->>主播B: 邀请PK(带上主播A的uid、cname、Token等信息)
主播B-->>业务服务器: 同意PK
业务服务器-->>主播A: 对端同意PK(带上主播B的uid、cname、Token等信息)
rect rgb(191, 223, 255)
主播A ->> NERtcSDK: startChannelMediaRelay 开启媒体转发
主播A ->> NERtcSDK: addLiveStream 开始旁路推流
NERtcSDK -->> 主播A: onLiveStreamState 监听旁路推流状态
主播A ->> NERtcSDK: stopPushStreaming 旁路推流成功后,停止推流
Note right of 主播A: 当主播B开始MediaRelay后,更新旁路推流,具体请根据实际业务进行调整
主播A ->> NERtcSDK: updateLiveStreamTask 更新旁路推流
Note right of 主播A: 根据回调确认mediaRelay是否成功
NERtcSDK -->> 主播A: onMediaRelayStatesChange 和 onMediaRelayReceiveEvent
end
NERtcSDK -->> 主播A: 监听房间中人员进入和音视频打开的回调
NERtcSDK -->> 主播B: 监听房间中人员进入和音视频打开的回调
主播A ->> 业务服务器: 结束PK
业务服务器 ->> 主播B: 结束PK
主播A ->> NERtcSDK: startPushStreaming 重新开始单人直播推流
NERtcSDK -->> 主播A: onStartPushStreaming
主播A ->> NERtcSDK: stopChannelMediaRelay 停止媒体转发
主播A ->> NERtcSDK: removeLiveStreamTask 移除旁路推流任务
主播B ->> NERtcSDK: stopChannelMediaRelay
主播B ->> NERtcSDK: removeLiveStreamTask 移除旁路推流任务
实现方法
开始 PK
-
开始 mediaRelay。
主播 A 调用
startChannelMediaRelay
方法开启媒体转发功能,将主播 A 的视频流推送到主播 B 房间。 -
开启旁路推流任务。
主播 A 调用
addLiveStreamTask
方法添加旁路推流任务,将主播 A 和 主播 B 房间的音视频流推送到 CDN 上进行合流。 -
等待旁路推流结果。
通过
onLiveStreamState
回调监听旁路推流状态,如果状态为STATE_PUSHING
, 表示旁路推流成功。如果旁路推流失败,则根据实际情况进行失败回退,例如调用
stopChannelMediaRelay
方法停止媒体转发功能。 -
停止单人直播推流。
主播 A 调用
stopPushStreaming
方法停止单人直播推流。 -
等待主播 B 加入房间后更新旁路推流任务。
主播 A 调用
updateLiveStreamTask
方法更新旁路推流任务,保证主播房间和挑战者房间的音视频流能够同步播放。 -
确认 mediaRelay 是否成功。
通过
onMediaRelayStatesChange
和onMediaRelayReceiveEvent
回调监听媒体转发状态,确认媒体转发是否成功。如果媒体转发失败,则根据实际情况进行失败回退,例如调用
stopChannelMediaRelay
和removeLiveStreamTask
方法结束 PK。
结束PK
-
开始单人直播推流。
主播 A 调用
startPushStreaming
方法开始单人直播推流。 -
等待单人直播推流结果。
主播 A 通过
onStartPushStreaming
回调监听单人直播推流状态,如果推流成功,则执行下一步操作。 -
停止mediaRelay。
主播 A 和 主播 B 分别调用
stopChannelMediaRelay
方法停止媒体转发功能。 -
移除旁路推流任务。
主播 A 和 主播 B 分别调用
removeLiveStreamTask
方法移除旁路推流任务。
示例代码
public void enterPK(String channelName, String token, long uid) {
//step1 开始mediaRelay(startMediaRelay)
NERtcMediaRelayParam mediaRelayParam = new NERtcMediaRelayParam();
NERtcMediaRelayParam.ChannelMediaRelayConfiguration config = mediaRelayParam.new ChannelMediaRelayConfiguration();
NERtcMediaRelayParam.ChannelMediaRelayInfo relayInfo = mediaRelayParam.new ChannelMediaRelayInfo(token, channelName, 0);
config.setDestChannelInfo(channelName, relayInfo);
NERtcEx.getInstance().startChannelMediaRelay(config);
//step2 开启旁路推流任务(addLiveStream)
NERtcEx.getInstance().addLiveStreamTask(taskInfo, (taskId, errCode) -> {});
//step3 等待旁路推流结果(onLiveStreamState), 如果state为STATE_PUSHING表示添加旁路任务成功,否则停止cdn推流(stopPushStreaming)
//step4 等待pk对方加入房间后更新旁路推流任务 updateLiveStreamTask
//step5 确认mediaRelay是否成功,如果失败根据实际情况做相应处理
//等待mediaRelay任务状态回调onMediaRelayStatesChange和onMediaRelayReceiveEvent确认mediaRelay是否成功
}
public void leavePK() {
//step1 开始cdn推流(startPushStreaming)
NERtcEx.getInstance().startPushStreaming(pushStreamingConfig);
//step2 等待cdn推流结果回调(onStartPushStreaming)
//成功后停止mediaRelay(stopMediaRelay)和移除旁路推流任务(removeLiveStreamTask)
//NERtcEx.getInstance().stopChannelMediaRelay();
//NERtcEx.getInstance().removeLiveStreamTask(taskId, (DeleteLiveTaskCallback) (taskId, errCode) -> {});
}
实现直播过程中连麦
下文介绍在单人直播的过程中,观众连麦场景下,NERTC 的实现流程。
API 时序图
sequenceDiagram
actor 主播A
participant NERtcSDK
participant 业务服务器
actor 连麦者
Note over 主播A, 连麦者: 开始连麦
连麦者->>业务服务器: 申请上麦
Note right of 主播A: 请自行实现相关业务逻辑
业务服务器->>主播A: 申请上麦
主播A-->>业务服务器: 同意上麦
业务服务器-->>连麦者: 主播同意上麦
连麦者 ->> NERtcSDK: joinChannel
rect rgb(191, 223, 255)
主播A ->> NERtcSDK: addLiveStreamTask 开始旁路推流
NERtcSDK -->> 主播A: onLiveStreamState
主播A ->> NERtcSDK: stopPushStreaming 旁路推流成功后,停止推流
Note over 主播A, 连麦者: 连麦状态下新增连麦
主播A ->> NERtcSDK: updateLiveStreamTask 更新旁路推流
Note over 主播A, 连麦者: 结束连麦
连麦者 ->> 业务服务器: 下麦
业务服务器 ->> 主播A: 下麦
主播A ->> NERtcSDK: startPushStreaming 重新开始推流
NERtcSDK -->> 主播A: onStartPushStreaming
主播A ->> NERtcSDK: removeLiveStreamTask 移除推流任务
end
连麦者 ->> NERtcSDK: leaveChannel
实现方法
开始连麦
-
开启旁路推流任务。
主播 A 调用
addLiveStreamTask
方法添加旁路推流任务,将主播房间和连麦者的音视频流推送到 CDN 上进行合流。 -
等待旁路推流结果。
通过
onLiveStreamState
回调监听旁路推流状态,如果状态为STATE_PUSHING
, 表示旁路推流成功。如果旁路推流失败,则调用removeLiveStreamTask
方法移除推流任务。 -
旁路推流成功后,停止单人直播推流。
主播 A 调用
stopPushStreaming
方法停止单人直播推流。
结束连麦
-
开始单人直播推流。
主播 A 调用
startPushStreaming
方法开始单人直播推流。 -
等待单人直播推流结果。
主播 A 通过
onStartPushStreaming
回调监听单人直播推流状态,如果推流成功,则执行下一步操作。 -
移除旁路推流任务。
主播 A 和 主播 B 分别调用
removeLiveStreamTask
方法移除旁路推流任务。
示例代码
public void enterSeat() {
//step1 开启旁路推流任务(addLiveStream)
NERtcEx.getInstance().addLiveStreamTask(taskInfo, (taskId, errCode) -> {});
//step2 等待旁路推流结果(onLiveStreamState), 如果state为STATE_PUSHING表示添加旁路任务成功,否则停止cdn推流(stopPushStreaming)
}
public void leaveSeat() {
//step1 开始cdn推流(startPushStreaming)
NERtcEx.getInstance().startPushStreaming(pushStreamingConfig);
//step2 等待cdn推流结果回调(onStartPushStreaming)
//成功后移除旁路推流任务(removeLiveStreamTask)
//NERtcEx.getInstance().removeLiveStreamTask(taskId, (DeleteLiveTaskCallback) (taskId, errCode) -> {});
}
常用的回调
请在初始化时注册推流相关的回调,以下列举推流需要关注的主要回调:
- 单人直播场景需要关注的主要回调如下:
//开始推流startPushStreaming结果回调 void onStartPushStreaming(int result, long channelId); //停止推流stopPushStreaming结果回调 void onStopPushStreaming(int result); //推流过程中断开,变为重连状态回调 void onPushStreamingReconnecting(int reason); //推流过程中重连成功回调 void onPushStreamingReconnectedSuccess(); //推流过程重连失败,最终断开回调 void onDisconnect(int reason);
- PK 场景需要关注的主要回调如下:
//开始推流startPushStreaming结果回调 void onStartPushStreaming(int result, long channelId); //停止推流stopPushStreaming结果回调 void onStopPushStreaming(int result); //推流过程中断开,变为重连状态回调 void onPushStreamingReconnecting(int reason); //推流过程中重连成功回调 void onPushStreamingReconnectedSuccess(); //推流状态已改变回调 void onLiveStreamState(String taskId, String pushUrl, int liveState); //跨房间媒体流转发状态发生改变回调 void onMediaRelayStatesChange(int state, String channelName); //媒体流相关转发事件回调 void onMediaRelayReceiveEvent(int event, int code, String channelName);
- 连麦场景需要关注的主要回调如下:
//开始推流startPushStreaming结果回调 void onStartPushStreaming(int result, long channelId); //停止推流stopPushStreaming结果回调 void onStopPushStreaming(int result); //推流过程中断开,变为重连状态回调 void onPushStreamingReconnecting(int reason); //推流过程中重连成功回调 void onPushStreamingReconnectedSuccess(); //推流状态已改变回调 void onLiveStreamState(String taskId, String pushUrl, int liveState);
播放器拉流
请使用网易云信播放器进行拉流播放,播放器的实现方法请参见实现播放功能。
为了避免在播放音视频媒体流时,因网络连接不稳定或者其他问题导致播放失败,请设置自动重试参数,以提高播放成功率和用户体验。