客户端实现
更新时间: 2025/06/03 16:25:09
本文为您展示通过 SDK 实现 在线直播场景的相关步骤,帮助您在业务中实时音视频通话、互动直播、在线直播、文字聊天、收发礼物等 IM、音视频通话 2.0 和互动直播 2.0 在 在线直播场景下的相关能力。
前提条件
在根据本文操作前,请确保您已完成以下操作:
- 在 网易云信控制台 上,完成创建应用,并获取到应用密钥。详情请参考 创建应用并获取 AppKey。
- 开通 IM 即时通讯、聊天室、音视频通话 2.0、旁路推流功能、和 NERoom 房间组件。详情请参考 开通产品。
集成 SDK
请参考下表,将相应的 SDK 或服务集成到您的项目中。
| 产品 | SDK 下载 | 集成文档 |
|---|---|---|
| IM 即时通讯(含信令) | IM SDK(含信令) | 集成 SDK |
| 音视频通话 2.0 | NERTC SDK | 集成 SDK |
第一步:初始化配置
-
业务应用服务器配置。
正式开始业务流程之前,您需要通过业务应用服务器完成以下步骤。
- 调用创建房间服务端接口,在返回参数中获取推拉流地址。详细操作请参考 直播管理相关 API。
- 创建音视频房间。详细操作请参考 创建房间。
- 创建聊天室。业务服务器维护聊天室列表及礼物信息。详细操作请参考 创建聊天室。
-
初始化并登录 IM。
初始化的详细说明请参考 初始化 IM SDK。
-
加入聊天室。
加入聊天室后可以参与文字聊天。Demo 中的逻辑规定,只有加入聊天室后才能开启直播。
-
设置音频参数和属性。
您可以根据对音质、声道、场景等的不同需求,通过 setAudioProfile 方法灵活设置音频属性,获得最佳实时互动效果。也可以通过 setLocalVideoConfig 设置视频发送配置。
示例代码:
Objective-C//1. 初始化并登录 IM。
//2. 加入聊天室。
// 进入聊天室
- (void)enterChatroom:(NIMChatroomEnterRequest *)request
completion:(nullable NIMChatroomEnterHandler)completion;
//3. 设置音频参数和属性。
// 设置视频发送配置(帧率/分辨率)
[[NERtcEngine sharedEngine] setLocalVideoConfig:config];
// 设置音频质量
[[NERtcEngine sharedEngine] setAudioProfile:profile scenario:scenario];
第二步:主播端开播
经过一系列初始化配置之后,主播端可以开启单人直播。
-
设置直播模式。
在互动直播的场景中,建议在加入房间前,通过 setChannelProfile 接口设置房间模式为直播模式。
-
启动音视频流,并打开推流开关。
调用 enableLocalVideo 开启本地视频采集和发送,并通过 setParameters 打开推流开关。
开启推流开关之后,主播或管理员创建推流任务之后才正式启动旁路推流。
-
设置本地视频画布。
通过 setupLocalVideoCanvas 设置本地视频画布,确定本地采集的视频画面。
-
初始化 NERTC SDK 并注册监听。
初始化的详细说明请参考 初始化 NERTC SDK。
-
设置角色为主播。
NERTC SDK 3.9.0 及后续版本支持直播场景下的用户角色管理,角色包括主播和观众。加入房间前可以通过 setClientRole 设置用户角色为主播。
-
加入音视频房间。
- 由于您已在第 1 步中创建了音视频房间,客户端可以直接通过参数 ChannelName 加入指定房间。若未提前创建房间,客户端也可以直接通过 joinChannel 直接加入房间,SDK 会在加入时自动创建一个房间。
- 安全模式下加入房间需要填写获取到的 Token。调试模式下,Token 请设置为 null。
-
配置推流状态监听。
主播或连麦者参与互动直播的过程中,可以通过 NERtcCallback 的 onNERTCEngineLiveStreamState 来监听推流状态。
-
新增并维护推流任务。
在成功加入房间后,通过 addLiveStreamTask 创建推流任务,将通话房间内的多媒体数据推至 CDN。常见的推流状态请参考 互动直播推流状态。
您也可以通过 服务端 API 创建推流任务。
示例代码:
Objective-C//1. 设置直播模式。 // 设置房间场景(直播) [[NERtcEngine sharedEngine] setChannelProfile:kNERtcChannelProfileLiveBroadcasting]; //2. 启动音视频流,并打开推流开关。 //启动音视频流 [[NERtcEngine sharedEngine] enableLocalAudio:YES]; [[NERtcEngine sharedEngine] enableLocalVideo:YES]; // 打开推流,回调摄像头采集数据 NSDictionary *params = @{ kNERtcKeyPublishSelfStreamEnabled: @YES, // 打开推流 kNERtcKeyVideoCaptureObserverEnabled: @YES // 将摄像头采集的数据回调给用户 }; [[NERtcEngine sharedEngine] setParameters:params]; //3. 设置本地视频画布。 - (int)setupLocalVideoCanvas:(NERtcVideoCanvas *)canvas; //4. 初始化 NERTC SDK 并注册监听。 NERtcEngineContext *context = [[NERtcEngineContext alloc] init]; context.engineDelegate = self; context.appKey = appkey; [[NERtcEngine sharedEngine] setupEngineWithContext:context]; //5. 加入音视频房间。 // 加入房间 - (int)joinChannelWithToken:(NSString *)token channelName:(NSString *)channelName myUid:(uint64_t)uId completion:(NERtcJoinChannelCompletion)completion; //6. 配置推流状态监听。 - (void)onNERTCEngineLiveStreamState:(NERtcLiveStreamStateCode)state taskID:(NSString *)taskID url:(NSString *)url; //7. 新增并维护推流任务。 // 示例 //先初始化推流任务 NERtcLiveStreamTaskInfo *info = [[NERtcLiveStreamTaskInfo alloc] init]; //taskID 可选字母、数字,下划线,不超过 64 位 info.taskID = taskID; // 设置推互动直播推流地址,一个推流任务对应一个推流房间 info.streamURL = pushUrl; // 设置是否进行互动直播录制,请注意与音视频通话录制区分。 info.serverRecordEnabled = NO; // 设置推音视频流还是纯音频流 info.lsMode = enableVideo ? kNERtcLsModeVideo : kNERtcLsModeAudio; //设置整体布局 NERtcLiveStreamLayout *layout = [[NERtcLiveStreamLayout alloc] init]; layout.width = 720; //整体布局宽度 layout.height = 1280; //整体布局高度 layout.backgroundColor = (red & 0xff) << 16 | (green & 0xff) << 8 | (blue & 0xff); info.layout = layout; // 设置直播成员布局 NERtcLiveStreamUserTranscoding *user1 = [[NERtcLiveStreamUserTranscoding alloc] init]; user1.uid = uid1; user1.audioPush = true; // 推流是否发布 user1 的音频 user1.videoPush = enableVideo; // 推流是否发布 user1 的视频 if (user1.videoPush) { // 如果发布视频,需要设置一下视频布局参数 user1.x = 10; // user1 的视频布局 x 偏移,相对整体布局的左上角 user1.y = 10; // user1 的视频布局 y 偏移,相对整体布局的左上角 user1.width = 180; // user1 的视频布局宽度 user1.height = 320; //user1 的视频布局高度 user1.adaption = kNERtcLsModeVideoScaleCropFill; } // 设置第 n 位直播成员布局 NERtcLiveStreamUserTranscoding *usern = [[NERtcLiveStreamUserTranscoding alloc]init]; usern.uid = uidn; usern.audioPush = true; usern.videoPush = enableVideo; if (usern.videoPush) { usern.adaption = kNERtcLsModeVideoScaleCropFill; usern.x = user1.x + user1.width + 10; usern.y = user1.y + user1.height + 10; usern.width = 320; usern.height = 640; } layout.users = @[user1,...,usern]; //配置背景占位图片,可以不配置。 NERtcLiveStreamImageInfo *imageInfo = [[NERtcLiveStreamImageInfo alloc] init]; imageInfo.url = url; imageInfo.x = 0; imageInfo.y = 0; imageInfo.width = 720; imageInfo.height = 1280; layout.bgImage = imageInfo; //调用 addLiveStreamTask 接口添加推流任务 int ret = [[NERtcEngine sharedEngine] addLiveStreamTask:info compeltion:^(NSString * _Nonnull taskId, kNERtcLiveStreamError errorCode) { NSString *toast = !errorCode ? @"添加成功": [NSString stringWithFormat:@"添加失败 errorcode = %d",errorCode]; MakeToast(toast); }]; if (ret != 0) { MakeToast(@"调用添加推流任务失败"); }
第三步:观众端观看
-
观众端加入聊天室。
观众端加入聊天室之后可以进行文字互动、打赏等操作。
-
观众端通过拉流地址拉流观看直播。
观众端通过播放器实现拉流收听,您可以使用网易云信提供的播放器 SDK 实现,详细操作请参考 集成 SDK。
第四步:主播在线直播
在线直播场景 Demo 中,主播 A 邀请主播 B 进行在线直播,主播 B 同意 PK 申请后,主播 A 和 B 删除推流任务、退出原有互动直播房间,并且请求服务器创建一个新的互动直播房间用于在线直播。主播 A 和 B 重新加入新房间之后,使用原有的推流地址重新推流,在新的互动直播房间中进行在线直播即可。
- 主播退出原直播房间之前,需要先删除推流任务,并在加入新房间后使用原推拉流地址重新推流,否则会因为重复推流造成推流失败。
- 观众端不需要切换推拉流地址,拉流出现断流时可以重新拉流解决问题。
操作步骤:
-
主播 A 通过信令发起 PK 邀请,并创建信令房间。
通过信令可以直接呼叫并创建信令房间,用于邀请其他主播进行 PK。
-
主播 B 接受 PK 邀请,并自动加入信令房间。
其中,参数 NIMSignalingAcceptRequest 中的 autoJoin 表示接受邀请后是否自动加入房间,请配置为 YES。主播 B 也可以拒绝邀请,详细操作请查看示例代码。
-
主播 A 和主播 B 删除推流任务、退出原房间并加入新的直播房间。
-
主播端设置远端画布。
- 监听远端用户加入房间与监听远端视频流发布。
- 设置远端画布、订阅远端视频流。
-
新增推流任务,观众端重新拉流。
新的推流任务中需要添加两个主播的原推流地址,观众端拉流时无需切换拉流地址。
示例代码:
Objective-C//1. 主播 A 通过信令发起 PK 邀请,并创建信令房间。 // 呼叫 - (void)signalingCall:(NIMSignalingCallRequest *)request completion:(nullable NIMSignalingCallBlock)completion; //2. 主播 B 接受 PK 邀请,并自动加入信令房间。 // 接受对方邀请并自动加入房间,参数 NIMSignalingAcceptRequest 中的 autoJoin 表示接受邀请后是否自动加入房间,请配置为 YES。 - (void)signalingAccept:(NIMSignalingAcceptRequest *)request completion:(nullable NIMSignalingAcceptBlock)completion; // 拒绝邀请 - (void)signalingReject:(NIMSignalingRejectRequest *)request completion:(nullable NIMSignalingOperationBlock)completion; //3. 主播 A 和主播 B 删除推流任务、退出原房间并加入新的直播房间。 // 先退出当前房间 [NERtcEngine.sharedEngine leaveChannel];; 离开房间 // 在退出成功的代理方法里,加入新房间 - (int)joinChannelWithToken:(NSString *)token channelName:(NSString *)channelName myUid:(uint64_t)uId completion:(NERtcJoinChannelCompletion)completion; //4. 主播端设置远端画布。 //监听远端用户加入房间与监听远端视频流发布。 - (void)onNERtcEngineUserDidJoinWithUserID:(uint64_t)userID userName:(NSString *)userName; - (void)onNERtcEngineUserVideoDidStartWithUserID:(uint64_t)userID videoProfile:(NERtcVideoProfileType)profile; //设置远端画布、订阅远端视频流。 - (int)setupRemoteVideoCanvas:(NERtcVideoCanvas *)canvas forUserID:(uint64_t)userID; - (int)subscribeRemoteVideo:(BOOL)subscribe forUserID:(uint64_t)userID streamType:(NERtcRemoteVideoStreamType)streamType; //5. 新增推流任务,观众端重新拉流。
第五步:结束直播
-
调用接口 leaveChannel 离开房间。
-
调用接口 destroyEngine 销毁音视频实例。
在收到
onNERtcEngineDidLeaveChannelWithResult之后执行 destroyEngine 销毁实例。示例代码:
Objective-C//1. 离开房间。 //UI 挂断按钮事件 - (IBAction)onHungupAction:(UIButton *)sender { [NERtcEngine.sharedEngine leaveChannel]; [self dismiss]; } //2. 销毁音视频实例。 - (void)dealloc { [NERtcEngine destroyEngine]; //销毁实例 }
常见问题
如何实现在 PK 直播过程中,一方异常退出后,自动停止 PK?
可以开通实时音视频抄送,获取用户离开房间回调,或者开通 IM 登出事件消息抄送。您的业务层可以根据抄送,判断退出的一方失败,并结束 PK、删除推流任务。




