互动直播总结

版权声明:www.gudianxiaoshuo.com (古典小说网) 今日头条号: 古典古韵古典小说、讨厌编程 https://blog.csdn.net/shuilan0066/article/details/84985870

一 直播架构

纯直播逻辑

互动直播

二 主播创建互动房间

需要的信息

纯直播不需要登录网易SDK,但互动直播需要使用网易账号,登录网易SDK,登录成功,才可调用相关功能,所以,需要事先申请好网易IM账号。

另外和纯直播一样,需要申请一个频道 即推流地址、拉流地址。

 这个,在/v1/live/enter_class 进入课程接口中,咱们自己的服务器会给出

创建互动音视频房间的步骤:

1、 进入课程时,调用enter_class接口,服务器会返回该课程主播的网易IM账号、推流、拉流地址

2、主播创建房间

     1)创建roomname

     2) 调用网易SDK,CreateRoom (nim_vchat_create_room),创建该房间

    示例:

				nim::VChat::Opt2Callback cb = nbase::Bind(&ChatroomForm::CreateRoomCallback, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
				
				nim_comp::VideoManager::GetInstance()->CreateRoom(GetRoomName(), "", cb);

     3)在创建房间的回调函数CreateRoomCallback中,主播第一个加入该房间

     

		if (nim_comp::VideoManager::GetInstance()->JoinRoom(mode, GetRoomName(), GetRoomSessionId(), rtmp_url_, true, cb,m_nLayoutType))

   注,主播在加入房间时,对房间的 推流地址、合成画面布局、语音模式等进行设置

 ( 自定义布局调整 http://faq.yunxin.163.com/kb/main/#/item/KB0261

  示例:

bool VideoManager::JoinRoom(nim::NIMVideoChatMode mode, const std::string& room_name, const std::string& session_id, const std::string &rtmp_url, bool bypass_rtmp, nim::VChat::Opt2Callback cb,int nLayout)
{
	Json::FastWriter fs;
	Json::Value value;
	value[nim::kNIMVChatSessionId] = session_id;
	bool live = false;
	if (!rtmp_url.empty())
	{
		value[nim::kNIMVChatRtmpUrl] = rtmp_url;
		live = true;
	}
	if (bypass_rtmp)
	{
		value[nim::kNIMVChatBypassRtmp] = 1;
		live = true;
	}
	if (live)
	{
		value[nim::kNIMVChatCustomVideo] = 1;
	}
	{

		//kNIMVChatVideoFrameRateNormal = 0,		/**< 视频通话帧率默认值,最大取每秒15帧 */
		//	kNIMVChatVideoFrameRate5 = 1,		/**< 视频通话帧率 最大取每秒5帧 */
		//	kNIMVChatVideoFrameRate10 = 2,		/**< 视频通话帧率 最大取每秒10帧 */
		//	kNIMVChatVideoFrameRate15 = 3,		/**< 视频通话帧率 最大取每秒15帧 */
		//	kNIMVChatVideoFrameRate20 = 4,		/**< 视频通话帧率 最大取每秒20帧 */
		//	kNIMVChatVideoFrameRate25 = 5,		/**< 视频通话帧率 最大取每秒25帧 */

		value[nim::kNIMVChatVideoFrameRate] =  nim::kNIMVChatVideoFrameRate20;
		value[nim::kNIMVChatVideoQuality] = nim::kNIMVChatVideoQuality720p;//分辨率
	}
	{
		value[nim::kNIMVChatAudioHighRate] = 1; //语音高清模式
	

		value[nim::kNIMVChatVideoRecord] = 1; //需要服务器录制视频

		value["rtmp_record"] = 1; //互动直播录制开关

	}

	if (nLayout>=0)
	{
		value[nim::kNIMVChatSplitMode] = nLayout; //自定义布局

		if (nLayout == nim::kNIMVChatSplitCustomLayout)
		{

			std::wstring selfLayoutStr;

			std::wstring dir = QPath::GetAppPath();
			//测试的时候,给观众传入一个拉流地址
			std::wstring iniPath = dir + L"set.ini";
			if (PathFileExists(iniPath.c_str()))
			{
				TCHAR szPath[2000];
				std::wstring nSelfLayoutStr;

				GetPrivateProfileStringW(_T("Layout"), _T("nSelfLayout"), NULL, szPath, 2000, iniPath.c_str());
				if (_tcslen(szPath) > 0)
				{
					nSelfLayoutStr = szPath; //0,1,2,3
				}

				std::wstring selfLayoutItem = L"selfLayout";
				selfLayoutItem.append(nSelfLayoutStr);
				//
				//selfLayout0    selfLayout1

				GetPrivateProfileStringW(_T("Layout"), selfLayoutItem.c_str(), NULL, szPath, 2000, iniPath.c_str());
				if (_tcslen(szPath) > 0)
				{
					selfLayoutStr = szPath;
				}
			}
			
			value[nim::kNIMVChatCustomLayout] = nbase::UTF16ToUTF8(selfLayoutStr);

		}
	}





	std::string json_value = fs.write(value);
	return nim::VChat::JoinRoom(mode, room_name, json_value, cb);

     4)JoinRoomCallback

          在主播成功加入房间后,该房间才算创建成功,并可正常使用

          此时,调用/v1/live/switch_room接口,告知服务器,当前互动课程的roomname

          服务器收到后,会发送 switch_room push信息,

         push信息包含roomid,主播IM账号

         roomid用于连麦者加入房间使用

        主播IM账号,用于区分连麦者视频流中,哪一个是主播的视频流,以便区别对待

  5) 离开互动

       调用EndChat 结束互动

       示例:

void VideoManager::EndChat(const std::string& session_id)
{
	QLOG_APP(L"EndChat {0}") << session_id;
	Json::FastWriter fs;
	Json::Value value;
	value[nim::kNIMVChatSessionId] = session_id;
	std::string json_value = fs.write(value);
	nim::VChat::End(json_value);
}

     主播结束了互动,当房间还有连麦者情况下, 该房间还存在,且还能推流,观众看到的是连麦者的信息

                                                                              但其他观众不能再加入房间,因为只有主播在房间时,观众才能加入

     为防止这种情况,

     PC 端的逻辑是: 判断有无连麦者,有连麦者的情况下,无法结束,只有主播挂断连麦者后,主播才能结束互动。

     主播目前无法暂停,暂停使用的逻辑也是结束互动,调用/v1/live/pause_live 接口,连麦者收到,pause_live push 消息后,各端退出

     继续直播使用 重新创建房间开始新互动逻辑。

三   互动过程信息回调

       互动过程中,网易会回调相关信息

       前提,在SDK初始化时,注册相关回调

	//注册音视频回调
	nim::VChat::SetVideoDataCb(true, nim_comp::VChatCallback::VideoCaptureData);
	nim::VChat::SetVideoDataCb(false, nim_comp::VChatCallback::VideoRecData);
	nim::VChat::SetCbFunc(nim_comp::VChatCallback::VChatCb);

       videoCaptureData捕获的是自己本端的视频数据

       videoRecData      捕获的是中转服务器转发来的其它连麦者的视频数据

                                    其中,同时传来该视频帧所对应的连麦者的 网易IM账号

      比如,将传来的视频帧,存入本端容器中,json数据是该视频帧所属者的IM账号

     std::map<std::string, PicRegion*> recv_video_pic_list_;  

void VChatCallback::VideoRecData(unsigned __int64 time, const char* data, unsigned int size, unsigned int width, unsigned int height, const char *json, const void *user_data)
{
	std::string json_temp(json);
	VideoManager::GetInstance()->video_frame_mng_.AddVideoFrame(false, time, data, size, width, height, json_temp, nim_comp::VideoFrameMng::Ft_I420);
}

  本端视频,存入容器中 PicRegion capture_video_pic_;

void VChatCallback::VideoCaptureData(unsigned __int64 time, const char* data, unsigned int size, unsigned int width, unsigned int height, const char *json, const void *user_data)
{

	VideoManager::GetInstance()->m_curCameraWidth = width;
	VideoManager::GetInstance()->m_curCameraHeight = height;

	std::string json_temp(json);
	VideoManager::GetInstance()->video_frame_mng_.AddVideoFrame(true, time, data, size, width, height, json_temp, nim_comp::VideoFrameMng::Ft_I420);
}

        VChatCb             互动过程中,一些事件回调

在网易事件回调信息VideoManager::OnVChatEvent中,我们可以获得上行网速等信息、连麦者加入退出信息等

      如:

   网速等信息

void VideoManager::OnVChatEvent(nim::NIMVideoChatSessionType type, uint64_t channel_id, int code, const std::string& json)
{
	QLOG_APP(L"OnVChatEvent type={0}, channel_id={1}, code={2}, json={3}") << type << channel_id << code << json;
	switch (type)
	{

	case nim::kNIMVideoChatSessionTypeInfoNotify:{
		Json::Value valus;
		Json::Reader reader;
		if (reader.parse(json, valus) && valus[nim::kNIMVChatStaticInfo].isObject())
		{
			Json::Value valus_info = valus[nim::kNIMVChatStaticInfo];
			int video_width = valus_info[nim::kNIMVChatVideo]["width"].asInt();                    //分辨率
			int video_height =  valus_info[nim::kNIMVChatVideo]["height"].asInt();

			int video_fps = valus_info[nim::kNIMVChatVideo][nim::kNIMVChatFPS].asInt();             //上行帧率
			int video_KBps = valus_info[nim::kNIMVChatVideo][nim::kNIMVChatKBPS].asInt();           //上行网速
			int video_loss_rate = valus_info[nim::kNIMVChatVideo][nim::kNIMVChatLostRate].asInt();  //丢包率

			int audio_fps = valus_info[nim::kNIMVChatAudio][nim::kNIMVChatFPS].asInt();             //音频帧率
			int audio_KBps = valus_info[nim::kNIMVChatAudio][nim::kNIMVChatKBPS].asInt();
			int audio_loss_rate = valus_info[nim::kNIMVChatAudio][nim::kNIMVChatLostRate].asInt();

       

 连麦者加入退出事件

	case nim::kNIMVideoChatSessionTypePeopleStatus:{
		VideoForm *window = (VideoForm*)(WindowsManager::GetInstance()->GetWindow(VideoForm::kClassName, VideoForm::kClassName));
		if (window && window->IsStart())
		{
			if (code == nim::kNIMVideoChatSessionStatusJoined)
			{
				window->OnComeIn(0);
			}
			else if (code == nim::kNIMVideoChatSessionStatusLeaved)
			{
				window->OnComeOut(0);
			}
		}
		else if (chatroom_people_cb_)
		{
			Json::Value valus;
			Json::Reader reader;
			if (reader.parse(json, valus))
			{
				std::string uid = valus[nim::kNIMVChatUid].asString();
				if (!uid.empty())
				{
					chatroom_people_cb_(uid, code == nim::kNIMVideoChatSessionStatusJoined);
				}
			}
		}
	}break;

四 与自己服务器逻辑     

 1)/v1/live/enter_class  进入课程,获得相关课程信息、主播IM账号  推流拉流地址

    http://gitlab.xnwimg.com/XNW/api/wikis/enter_live_class

   (若观众端调用此接口进入,当主播正在互动时,则服务器会返回互动信息比如课程模式、roomname等)

 2)点击上课后,会发送上课请求

    http://gitlab.xnwimg.com/XNW/api/wikis/start_live_class

 3)主播创建好房间并加入房间后,给服务器发送新的roomname

  http://gitlab.xnwimg.com/WEB/xnw/wikis/live_switch_room

   服务器收到后,发送push消息

   http://gitlab.xnwimg.com/WEB/xnw/wikis/live_interact_push

   各观众端,收到push消息,或者roomname

(若观众目前离线,在再进入课程时,会从课程信息中获得)

4)主播暂停后,退出直播间,通知给服务器

   http://gitlab.xnwimg.com/XNW/api/wikis/pause_live_class

   连麦者收到后,各自退出,转为观众状态

   同时,主播暂停时,会发送禁止举手请求 /v1/live/switch_handup

   http://gitlab.xnwimg.com/WEB/xnw/wikis/live_switch_handup

   禁止观众举手

   

   

5)主播继续后,开启新的互动房间

     首先调用开始直播,告知服务器,从暂停状态,转为继续直播状态

      http://gitlab.xnwimg.com/XNW/api/wikis/start_live_class

     然后,等主播创建新房间成功后,

     参考第二步,发送服务器新的roomname

     观众重新申请举手等

6)结课逻辑

      目前,PC使用的结课逻辑是:

     正常情况:

      主播点击 结束课程,

      首先,判断是否还有连麦者,有的话,需要pad挂断连麦者,过段时间再重试。

      PAD挂断后,到网易SDK判断该连麦者退出,需要30-60秒左右时间

      所以,若有连麦者的话,从挂断开始,约1分钟后重试,才能结束掉。

      若无连麦者,结束后,会向服务器发送结束课程请求 /v1/live/end_live

    http://gitlab.xnwimg.com/XNW/api/wikis/end_live_class

   超时情况, 离下课时间1小时后,系统会默认强制结课

   此时,主播会直接关闭互动,发送end_live结课请求

               连麦端收到end_live push消息后,自动退出,结束课程

     

    (正常结课 是否可修改为:不用判断是否有连麦,直接发送end_live, 各端收到后,自动退出)

     
五 常见错误信息

NODE_ADD_MEETING_MODE_ERROR = 102, //会议模式错误
NODE_ADD_RTMP_MODE_ERROR = 103, //非rtmp用户加入rtmp频道
NODE_ADD_RTMP_NODES_ERROR = 104, //超过互动直播频道人数限制
NODE_ADD_RTMP_HOST_ERROR = 105, //已经存在一个主播
NODE_ADD_RTMP_CREATE_ERROR = 106, //需要旁路直播, 但频道创建者非主播
NODE_DISCONNECT_SERVER = 150, //节点和服务器心跳超时
NODE_RTMP_SUCCESS_CODE = 200, //正确返回码
NODE_RTMP_START_ALREADY_ON = 201, //本节点已经直播,无需重复开启
NODE_RTMP_START_EXCEED_MAX = 202, //超过最大允许直播节点数量
NODE_RTMP_START_NO_FIRST_HOST= 203, //必须由主播第一个开启直播
NODE_RTMP_START_RTMPSERVER_ERROR= 204, //互动直播服务器错误
NODE_RTMP_START_OTHER_ERROR= 205, //其它错误
NODE_RTMP_START_HOST_DUPLICATE= 206, //重复的主播
NODE_RTMP_START_HOST_ERROR= 207, //频道支持直播,主播不支持直播
NODE_RTMP_LAYOUT_ERROR = 208, //互动直播主播设置自定义布局参数错误
NODE_RTMP_STOP_ALREADY_OFF = 250, //本节点已经停止直播,无需重复停止
NODE_RTMP_NO_RESPONSE = 404 //服务器无响应
RTMP_INITIAL = 500, //初始化
RTMP_LAYOUT_ERROR = 501, //主播设置定制布局,布局参数错误
RTMP_START_CONNECTTING = 502, //开始连接
RTMP_CONNECTTED = 503, //连接成功
RTMP_CONNECT_FAIL = 504, //连接失败
RTMP_PUSHING = 505, //推流中
RTMP_PUSH_FAIL = 506, //互动直播推流失败
RTMP_INNER_ERROR = 507, //内部错误
RTMP_PEOPLE_COUNT_LIMIT = 508, //人数超出限制
NODE_AUDIO_SAMPLE_RATE_ERROR = 301, //音频采样率有问题

自己曾遇到的错误信息:

28   http请求超时,网络很差导致

101 主播开启互动房间,出现 客户端连接turn服务器失败

       主播网络是否有限制,比如UDP协议是否通

      (自己关了软件,重新开启后,正常)

106 需旁路直播,但频道创建者非主播

104 超过人数限制,  我测试的是,默认布局,只支持3个连麦者,自定义布局才支持四个连麦者

208 主播设置的定制布局参数出错

302 Appkey不对应

404 服务器无响应,或 房间不存在

405 设置主画面时,出现405错误

       说明,传入的学生账号ACCID不正确

       MainPictureOptUidNotExist

408 没有登录成功

       或其他导致建立长连接失败 

        需提供SDK日志,网易协调排查

417 重复,可能房间已经存在

1001  主动结束通话   VChatConnectLogout

11001 error_user_offline

           error_Disconnect_server_timeout

          网络不好导致

11403 无效的操作

      

参考资料:

https://dev.yunxin.163.com/docs/product/%E4%BA%92%E5%8A%A8%E7%9B%B4%E6%92%AD/%E6%96%B0%E6%89%8B%E6%8E%A5%E5%85%A5%E6%8C%87%E5%8D%97

https://faq.yunxin.163.com/

https://blog.csdn.net/shuilan0066/article/details/80952007

猜你喜欢

转载自blog.csdn.net/shuilan0066/article/details/84985870