互动直播房间接入
网易云信提供简单的互动直播和连麦接口,只需要创建并加入互动房间即可以实现直播推流;连麦者使用相同的房间名加入互动房间即可以实现实时连麦互动。阅读该章节,您可以迅速完成一个最简单的互动直播房间的创建、加入,快速实现互动直播的功能。
在这里需要明确几个基本概念: 房间:互动直播房间与云通信音视频多人会议的房间概念一致,以房间名称为唯一标识。互动直播房间需要先创建成功后才能加入,当所有用户都离开房间后,可以复用该房间名重新创建。 主播:是互动直播房间的主用户,推流地址的指定者,直播的主画面源。主播需要首先加入房间。一个互动直播房间同时只能有一个主播。 连麦者:是互动直播房间的次用户,直播辅画面源,与主播加入同一房间,即能实现实时连麦互动,需要主播在房间时才能加入。 观众:互动直播中除了主播和连麦者,观看直播画面的其他用户。可以通过停止播放直播并加入互动房间转变为连麦者。
另外,理解网易云信互动直播与音视频音视频通话的关系可以更好地帮助开发者快速集成: 互动直播与多人音视频通话:云通信互动直播基于多人音视频通话开发,通过将多人会议中用户的音视频数据处理后推送给视频流服务器实现直播和实时连麦。在功能的提供上,互动直播复用多人音视频接口,增加互动开关、推流地址指定与切换、直播角色指定等扩展设置。
互动直播房间接入流程
创建互动直播房间
API介绍
创建一个互动直播房间(后续需要主动调用加入接口进入房间)。其中webrtc标记支持webrtc互通,无需要不要打开。房间推流的配置信息需要从扩展字段传入。
API原型
C++
static void CreateRoom(const std::string& room_name, const std::string& custom_info, const std::string& json_extension, Opt2Callback cb)
File:nim_cpp_vchat.h
Namespace:NIM
Class:VChat
C#
public static void CreateRoom(string room_name, string custom_info, NIMCreateRoomJsonEx createRoomInfo, NIMVChatOpt2Handler cb)
Namespace:NIM
Class:VChatAPI
C
void nim_vchat_create_room(const char *room_name, const char *custom_info, const char *json_extension, nim_vchat_opt2_cb_func cb, const void *user_data)
File:nim_vchat.h
参数说明
参数 | 类型 | 说明 |
---|---|---|
room_name | string | 房间名 |
custom_info | string | 自定义信息,所有加入房间的成员都会收到此信息 |
json_extension(C/C++) | string | Json string 扩展,房间配置信息,详见nim_vchat_def.h |
createRoomInfo(C#) | Json | C接口中json_extension的封装类,见NIMCreateRoomJsonEx |
cb | function | 回调函数 |
user_data(C) | void* | APP的自定义用户数据,SDK只负责传回给回调函数cb,不做任何处理! |
返回值说明
无返回值
示例
C++
void foo() { nim::VChat::Opt2Callback create_room_cb = [](int code, __int64 channel_id, const std::string& json_extension) { switch (code) { case 200: //创建房间成功 //保存channel_id ... case 417: //房间名已存在 ... default: ... } }; std::string room_name("room1"); nim::VChat::CreateRoom(room_name, "", "", create_room_cb); }
C#
void CreateRoomCallback(int code,long channel_id, string json_extension,IntPtr user_data) { switch (code) { case 200: //创建房间成功 //保存channel_id ... case 417: //房间名已存在 ... default: ... } } void foo() { string room_name = "room1"; string custom_info = "custom_info"; NIMCreateRoomJsonEx extension = null; NIM.VChatAPI.CreateRoom(room_name, custom_info, extension , CreateRoomCallback); }
C
typedef void(*nim_vchat_create_room)(const char *room_name, const char *custom_info, const char *json_extension, nim_vchat_opt2_cb_func cb, const void *user_data); void CreateRoomCallback(int code, int64_t channel_id, const char *json_extension, const void *user_data) { switch (code) { case 200: //创建房间成功 //保存channel_id ... case 417: //房间名已存在 ... default: ... } } void foo() { nim_vchat_create_room func = (nim_vchat_create_room) GetProcAddress(hInst, "nim_vchat_create_room"); func("room1", "", "", CreateRoomCallback, NULL); }
特殊说明
返回错误码中417说明已经存在同名的房间,如果是目标房间议,则可以直接走后面流程加入此房间。如果不是希望创建的目标房间,则需要重新设定房间名后再创建。
加入互动直播房间
API介绍
加入一个互动直播房间,主播必须先进入房间。
API原型
C++
static bool JoinRoom(NIMVideoChatMode mode, const std::string& room_name, const std::string& json_extension, Opt2Callback cb)
File:nim_cpp_vchat.h
Namespace: nim
Class:VChat
C#
static bool JoinRoom(NIMVideoChatMode mode, string room_name, NIMJoinRoomJsonEx joinRoomInfo, NIMVChatOpt2Handler cb)
Namespace:NIM
Class:VChatAPI
C
bool nim_vchat_join_room(enum NIMVideoChatMode mode, const char *room_name, const char *json_extension, nim_vchat_opt2_cb_func cb, const void *user_data)
File:nim_vchat.h
参数说明
主播加入必须填写推流地址,打开推流开关。连麦互动者必须打开推流开关。普通成员直接进入。
参数 | 类型 | 说明 |
---|---|---|
mode | enum | 音视频通话类型,见nim_vchat_def.h |
room_name | string | 房间名 |
json_extension(C/C++) | string | Json string 扩展,音视频通话的扩展参数设置 |
joinRoomInfo(C#) | object | C接口中json_extension的封装类,见NIMJoinRoomJsonEx |
cb | function | 结果回调 |
user_data(C) | void* | APP的自定义用户数据,SDK只负责传回给回调函数cb,不做任何处理! |
其中扩展参数中NIMVChatVideoSplitMode的定义说明见图文介绍;在NIMVChatVideoSplitMode设置为kNRTCChatSplitCustomLayout时可使用自定义布局,说明见布局参数配置介绍。
返回值说明
返回一个bool类型值。接口调用成功返回true,否则返回false。失败一般是由于已存在通话,无法重复发起。
示例
C++
void OnOpt2Callback(int code, __int64 cannel_id, const char *json_extension, const void *user_data) { } void foo() { Json::FastWriter fs; Json::Value value; value[nim::kNIMVChatSessionId] = session_id; value[nim::kNIMVChatBypassRtmp] = 1;//主播和连麦者必须打开推流开关 value[nim::kNIMVChatRtmpUrl] = "rtmp://...";//主播必须填写推流地址 value[nim::kNIMVChatVideoQuality] = kNIMVChatVideoQuality540p;//分辨率 std::string json_value = fs.write(value); nim::VChat::JoinRoom(nim::kNIMVideoChatModeAudio, "room_name", json_value, OnOpt2Callback); }
C#
void JoinMultiVChatRoomCallback(int code, Int64 channel_id, string json_extension,IntPtr user_data) { if (code==200) { } else { Action action = () => { MessageBox.Show("加入房间失败-错误码:" + code.ToString()); }; this.BeginInvoke(action); } } void foo() { NIM.NIMJoinRoomJsonEx joinRoomJsonEx = new NIMJoinRoomJsonEx(); joinRoomJsonEx.SessionId = Guid.NewGuid().ToString("N"); joinRoomJsonEx.BypassRtmp = 1;//主播和连麦者必须打开推流开关 joinRoomJsonEx.RtmpUrl = "rtmp://...";//主播必须填写推流地址 joinRoomJsonEx.VideoQuality = NIMVChatVideoQuality.kNIMVChatVideoQuality540p; string room_name = "room1"; Action action = () => { if (VChatAPI.JoinRoom(NIMVideoChatMode.kNIMVideoChatModeVideo, room_name, joinRoomJsonEx, _joinroomcb)) { //调用成功 } else { string info = String.Format("加入房间-{0}-失败", room_name); MessageBox.Show(info); } }; this.Invoke(action); }
C
void OnOpt2Callback(int code, __int64 cannel_id, const char *json_extension, const void *user_data) { } typedef bool(*nim_vchat_join_room)(NIMVideoChatMode mode, const char *room_name, const char *json_extension, nim_vchat_opt2_cb_func cb, const void *user_data); void foo() { nim_vchat_join_room func = (nim_vchat_join_room) GetProcAddress(hInst, "nim_vchat_join_room"); Json::FastWriter fs; Json::Value value; value[nim::kNIMVChatSessionId] = session_id; value[nim::kNIMVChatBypassRtmp] = 1;//主播和连麦者必须打开推流开关 value[nim::kNIMVChatRtmpUrl] = "rtmp://...";//主播必须填写推流地址 value[nim::kNIMVChatVideoQuality] = kNIMVChatVideoQuality540p;//分辨率 std::string json_value = fs.write(value); func(nim::kNIMVideoChatModeAudio, "room_name", json_value, cb); }
离开互动直播房间
API介绍
需要在结束时调用,用于底层挂断和清理数据。
API原型
C++
static void End(const std::string& json_extension);
File:nim_cpp_vchat.h
Namespace:NIM
Class:VChat
C#
public static void End(string jsonExtension="")
Namespace:NIM
Class:VChatAPI
C
void nim_vchat_end(const char *json_extension)
File:nim_vchat.h
参数说明
需要带上加入时填写的session_id。
- C++
参数 | 类型 | 说明 |
---|---|---|
json_extension | string | Json string 扩展,kNIMVChatSessionId |
- C#
参数 | 类型 | 说明 |
---|---|---|
jsonExtension | string | Json string 扩展,kNIMVChatSessionId |
- C
参数 | 类型 | 说明 |
---|---|---|
json_extension | string | Json string 扩展,kNIMVChatSessionId |
返回值说明
无返回值。
示例
C++
void foo() { Json::FastWriter fs; Json::Value value; value[nim::kNIMVChatSessionId] = session_id; std::string json_value = fs.write(value); nim::VChat::End(json_value); }
C#
void foo() { string json = "{\"session_id\":\"session_id_temp\"}"; NIM.VChatAPI.End(json); }
C
typedef void(*nim_vchat_end)(const char* json_extension); void foo() { nim_vchat_end func = (nim_vchat_end) GetProcAddress(hInst, "nim_vchat_end"); Json::FastWriter fs; Json::Value value; value[nim::kNIMVChatSessionId] = session_id; std::string json_value = fs.write(value); func(json_value.c_str()); }
用户进出房间通知
API介绍
在连接建立后,如果已有成员在通话中,或新进来的成员都会通过此回调通知。有成员离开也通过此回调,并告诉是正常离开还是超时离开,超时离开代表本地超时未收到对端数据,可能对方网络异常也可能是本地网络异常。
API原型
C#
NIMVChatSessionStatus.onSessionPeopleStatus
public delegate void onSessionPeopleStatusHandler(long channel_id, string uid, int status)
Namespace:NIM
Class:VChatAPI
C++/C
typedef void (*nim_vchat_cb_func)(enum NIMVideoChatSessionType type, int64 channel_id, int code, const char *json_extension, const void *user_data)
NIMVideoChatSessionType::kNIMVideoChatSessionTypePeopleStatus
File:nim_vchat_def.h
参数说明
- C#
参数 | 类型 | 说明 |
---|---|---|
channel_id | long | 频道id |
uid | string | 对方id |
status | int | 成员状态,离开、加入等 |
- C++/C
参数 | 类型 | 说明 |
---|---|---|
type | enum | 回调类型kNIMVideoChatSessionTypePeopleStatus |
channel_id | int64 | 频道id |
code | int | 状态码,对应NIMVideoChatSessionStatus |
json_extension | string | Json string 扩展,返回kNIMVChatUid,如果是离开带kNIMVChatStatus对应NIMVideoChatUserLeftType |
user_data | void* | 注册回调时的APP自定义用户数据,SDK只负责传回给回调函数cb,不做任何处理 |
示例
C#
private static void OnSessionPeopleStatus(long channel_id, string uid, int status) { DemoTrace.WriteLine("SessionPeopleStatus channel_id:" + channel_id.ToString() + " status:" + status.ToString() + " uid:" + uid); if (status == NIMVideoChatSessionStatus.kNIMVideoChatSessionStatusJoined) { MessageBox.Show("用户加入"); } else if (status == NIMVideoChatSessionStatus.kNIMVideoChatSessionStatusLeaved) { MessageBox.Show("用户离开"); } }
C++/C
void VChatCb(nim::NIMVideoChatSessionType type, __int64 channel_id, int code, const char *json, const void*) { switch (type) { case nim::kNIMVideoChatSessionTypePeopleStatus:{ if (code == nim::kNIMVideoChatSessionStatusJoined) { //用户加入 } else if (code == nim::kNIMVideoChatSessionStatusLeaved) { //用户离开 Json::Value valus; Json::Reader reader; if (reader.parse(json, valus)) { std::string uid = valus[nim::kNIMVChatUid].asString(); int32_t leave_type = valus[nim::kNIMVChatStatus].asInt(); QLOG_APP(L"vchat people leave uid: {0}, leave_type {1}") << uid << leave_type; } } }break; //··· } }
互动直播状态回调
API介绍
在连接建立后,服务器会定时刷新当前的直播状态,并告知客户端,客户端会收到当前最新的状态,但是有可能丢失过程状态。比如直播发起够快的话,直播的开始连接等状态就会不提示,直接提示推流中。
API原型
C#
NIMVChatSessionStatus.onSessionLiveStateNotify
public delegate void OnSessionLiveStateInfoNotifyHandler(long channel_id, int code, NIMVChatLiveState state)
Namespace:NIM
Class:VChatAPI
C++/C
typedef void (*nim_vchat_cb_func)(enum NIMVideoChatSessionType type, int64 channel_id, int code, const char *json_extension, const void *user_data)
NIMVideoChatSessionType::kNIMVideoChatSessionTypeLiveState
File:nim_vchat_def.h
参数说明
- C#
参数 | 类型 | 说明 |
---|---|---|
channel_id | long | 频道id |
code | int | 无效错误码 |
status | enum | 直播状态, 见NIMVChatLiveState |
- C++/C
参数 | 类型 | 说明 |
---|---|---|
type | enum | 直播状态,见kNIMVideoChatSessionTypeLiveState |
channel_id | int64 | 频道id |
code | int | 无效错误码 |
json_extension | string | Json string 扩展,返回kNIMVChatLiveState带kNIMVChatStatus对应NIMVChatLiveStateCode |
user_data | void* | 注册回调时的APP自定义用户数据,SDK只负责传回给回调函数cb,不做任何处理 |
- NIMVChatLiveState/NIMVChatLiveStateCode
枚举定义 | 值 | 说明 |
---|---|---|
kNIMVChatLiveStateInitial | 500 | 直播初始状态 |
kNIMVChatLiveStateLayoutError | 501 | 主播设置定制布局,布局参数错误 |
kNIMVChatLiveStateStartConnecting | 502 | 开始连接 |
kNIMVChatLiveStateConnectted | 503 | 连接成功 |
kNIMVChatLiveStateConnectFail | 504 | 连接失败 |
kNIMVChatLiveStatePushing | 505 | 推流中 |
kNIMVChatLiveStatePushFail | 506 | 互动直播推流失败 |
kNIMVChatLiveStateInnerError | 507 | 内部错误 |
kNIMVChatLiveStatePeopleLimit | 508 | 人数超出限制 |
示例
C#
private static void OnSessionPeopleStatus(long channel_id, int code, NIMVChatLiveState state) { if (status == NIMVChatLiveState.kNIMVChatLiveStateStartConnecting) { MessageBox.Show("直播开始连接"); } else if (status == NIMVChatLiveState.kNIMVChatLiveStateConnectted) { MessageBox.Show("直播连接成功"); } else if (status == NIMVChatLiveState.kNIMVChatLiveStatePushing) { MessageBox.Show("直播推流中"); } //... }
C++/C
void VChatCb(nim::NIMVideoChatSessionType type, __int64 channel_id, int code, const char *json, const void*) { switch (type) { case nim::kNIMVideoChatSessionTypeLiveState:{ Json::Value valus; Json::Reader reader; if (reader.parse(json, valus) && valus[nim::kNIMVChatLiveState].isObject()) { int32_t status = valus[nim::kNIMVChatLiveState][nim::kNIMVChatStatus].asInt(); if (status == nim::kNIMVChatLiveStateStartConnecting) { //直播开始连接 } else if (status == nim::kNIMVChatLiveStateConnectted) { //直播连接成功 } else if (status == nim::kNIMVChatLiveStatePushing) { //直播推流中 } //... } }break; //··· } }
房间发生了错误
API介绍
当房间发生异常,统一返回连接错误信息,和开始时连接成功及连接失败是同一个回调函数。
API原型
C#
NIMVChatSessionStatus.onSessionConnectNotify
public delegate void onSessionConnectNotifyHandler(long channel_id, int code, string record_file, string video_record_file)
Namespace:NIM
Class:VChatAPI
C++/C
typedef void (*nim_vchat_cb_func)(enum NIMVideoChatSessionType type, int64 channel_id, int code, const char *json_extension, const void *user_data)
NIMVideoChatSessionType::kNIMVideoChatSessionTypeConnect
File:nim_vchat_def.h
参数说明
- C#
参数 | 类型 | 说明 |
---|---|---|
channel_id | long | 频道id |
code | int | 状态码见NIMVChatConnectErrorCode |
record_file | string | 服务器录制的音频文件名 |
video_record_file | string | 服务器录制的视频文件名 |
- C++/C
参数 | 类型 | 说明 |
---|---|---|
type | enum | 回调类型kNIMVideoChatSessionTypeConnect |
channel_id | int64 | 频道id |
code | int | 错误码NIMVChatConnectErrorCode,200代表连接成功 |
json_extension | string | Json string 扩展,如果成功返回 kNIMVChatVideoRecordFile和kNIMVChatRecordFile |
user_data | void* | 注册回调时的APP自定义用户数据,SDK只负责传回给回调函数cb,不做任何处理 |
- NIMVChatConnectErrorCode
枚举定义 | 值 | 说明 |
---|---|---|
kNIMVChatConnectDisconn | 0 | 断开连接 |
kNIMVChatConnectStartFail | 1 | 启动失败 |
kNIMVChatConnectTimeout | 101 | 超时 |
kNIMVChatConnectMeetingModeError | 102 | 会议模式错误 |
kNIMVChatConnectRtmpModeError | 103 | 非rtmp用户加入rtmp频道 |
kNIMVChatConnectRtmpNodesError | 104 | 超过频道最多rtmp人数限制 |
kNIMVChatConnectRtmpHostError | 105 | 已经存在一个主播 |
kNIMVChatConnectRtmpCreateError | 106 | 需要旁路直播, 但频道创建者非主播 |
kNIMVChatConnectSuccess | 200 | 成功 |
kNIMVChatConnectLayoutError | 208 | 主播自定义布局错误 |
kNIMVChatConnectInvalidParam | 400 | 错误参数 |
kNIMVChatConnectDesKey | 401 | 密码加密错误 |
kNIMVChatConnectInvalidRequst | 417 | 错误请求 |
kNIMVChatConnectServerUnknown | 500 | 服务器内部错误 |
kNIMVChatConnectLogout | 1001 | 退出 |
kNIMVChatChannelStartFail | 11000 | 发起失败 |
kNIMVChatChannelDisconnected | 11001 | 断开连接 |
kNIMVChatVersionSelfLow | 11002 | 本人SDK版本太低不兼容 |
kNIMVChatVersionRemoteLow | 11003 | 对方SDK版本太低不兼容 |
示例
C#
private static void OnSessionConnectNotify(long channel_id, int code, string record_file, string video_record_file) { if (code == 200) { //连接成功 } else { //连接失败 NIM.VChatAPI.End(); } }
C++/C
void VChatCb(nim::NIMVideoChatSessionType type, __int64 channel_id, int code, const char *json, const void*) { switch (type) { case nim::kNIMVideoChatSessionTypeConnect:{ if (code == 200) { //连接成功 } else { //连接失败 } }break; //··· } }