本文主要介绍如何将 RTC Windows SDK 集成到你的项目中实现一个简单的视频直播。
开发环境要求
- 一个有效的 开发者账号。
- Windows Visual Studio 2017 或以上版本
- 运行在 Windows 7 及以上版本的 Windows 设备。
快速集成
获取应用的 App ID
-
- 创建项目
首先我们需要在 anyRTC 用户控制台创建一个「项目」。
-
- 获取 APP ID
获取项目的「APP ID」。
获取 SDK
快速集成包括获取 SDK 和引入 SDK 。
导入SDK
参考以下步骤创建一个 Windows 项目。
创建 Windows 项目
- 打开 Microsoft Visual Studio 并点击新建项目。
- 进入新建项目窗口,选择项目类型为 MFC 应用程序,输入项目名称,选择项目存储路径,并点击确认。
- 进入MFC 应用程序窗口,选择应用程序类型为基于对话框,并点击完成。
1. 配置项目文件
下载SDK后解压并打开。并将其中的 sdk 文件夹复制到你的项目文件夹下。
2. 配置项目属性
在解决方案资源管理器窗口中,右击项目名称并点击属性进行以下配置,配置完成后点击确定。
-
进入 C/C++ > 常规 > 附加包含目录菜单,点击编辑,并在弹出窗口中输入 $(SolutionDir)include。
-
进入链接器 > 常规 > 附加库目录菜单,点击编辑,并在弹出窗口中输入 $(SolutionDir)。
-
进入链接器 > 输入 > 附加依赖项菜单,点击编辑,并在弹出窗口中输入 ARtcKit.lib。
操作流程
初始化 SDK
使用 anyRTC SDK 的第一步,是先通过 createARRtcEngine
创建一个 IRtcEngine
对象的指针 IRtcEngine*
,并配置开发者信息和注册监听 SDK 事件的回调。
- 继承
IRtcEngineEventHandler
事件回调接口类,重写关键事件的回调接口,包括本地用户进房/退房事件、远端用户加入/退出事件、错误事件和警告事件等。 - 调用
initialize
接口配置开发者信息并注册监听 SDK 事件。
CArObject *CArObject::GetArObject(LPCTSTR lpAppId)
{
if (m_lpArObject == NULL)
m_lpArObject = new CArObject();
if (m_lpArEngine == NULL)
// 创建实例。
m_lpArEngine = (IRtcEngine *)createARRtcEngine();
if (lpAppId == NULL)
return m_lpArObject;
RtcEngineContext ctx;
// 添加注册回调和事件。
ctx.eventHandler = &m_EngineEventHandler;
#ifdef UNICODE
char szAppId[128];
::WideCharToMultiByte(CP_ACP, 0, lpAppId, -1, szAppId, 128, NULL, NULL);
// 输入你的 App ID。
ctx.appId = szAppId;
#else
ctx.appId = lpAppId;
#endif
// 初始化 IRtcEngine。
m_lpArEngine->initialize(ctx);
return m_lpArObject;
}
// 继承 IRtcEngineEventHandler 类中的回调与事件。
class CAGEngineEventHandler :
public IRtcEngineEventHandler
{
public:
CAGEngineEventHandler(void);
~CAGEngineEventHandler(void);
void SetMsgReceiver(HWND hWnd = NULL);
HWND GetMsgReceiver() {return m_hMainWnd;};
// 注册 onJoinChannelSuccess 回调。
// 本地用户成功加入频道时,会触发该回调。
virtual void onJoinChannelSuccess(const char* channel, uid_t uid, int elapsed);
// 注册 onLeaveChannel 回调。
// 本地用户成功离开频道时,会触发该回调。
virtual void onLeaveChannel(const RtcStats& stat);
// 注册 onUserOffline 回调。
// 远端用户离开频道或掉线时,会触发该回调。
virtual void onUserOffline(uid_t uid, USER_OFFLINE_REASON_TYPE reason);
private:
HWND m_hMainWnd;
};
设置频道场景
初始化结束后,调用 setChannelProfile
方法,将频道场景设为直播。
如果想切换为其他模式,需要先调用 leaveChannel
方法离开当前的频道 ,然后调用 setChannelProfile
设置新的频道场景。
// 设置频道场景为直播。
m_lpArEngine->setChannelProfile(CHANNEL_PROFILE_LIVE_BROADCASTING);
设置用户角色
直播模式下有两种用户角色:主播和观众,默认的角色为观众。设置频道场景为直播后,设置用户角色步骤为:
- 让用户选择自己的角色是主播还是观众。
- 调用
setClientRole
方法,根据设置不同的角色进行传参。
注意:
直播频道内的观众,只能看到主播的画面、听到主播的声音。加入频道后,如果你想切换用户角色,也可以调用 setClientRole
方法。
// 设置用户角色为主播。
m_lpArEngine->setClientRole(CLIENT_ROLE_BROADCASTER);
设置本地视图
anyRTC SDK 并不会默认打开视频模块,enableVideo
可以开启视频模块,开启模块后才能调用本地采集以及接收远端视频。
调用 enableVideo
开启视频模块。
调用 setupLocalVideo
接口,打开本地视频采集。
?>
1.在调用joinChannel
前,setupLocalVideo
并不会立即显示视频,需要调用startPreview
方法才能获得预览。
2.如果调用setupLocalVideo
方法后,立即调用joinChannel
后可立即显示本地视频。
// 启用视频模块。
m_lpArObject->GetEngine()->enableVideo();
// 设置本地视图。
VideoCanvas vc;
vc.uid = 0;
vc.view = m_wndLocal.GetSafeHwnd();
vc.renderMode = RENDER_MODE_FIT;
m_lpArObject->GetEngine()->setupLocalVideo(vc);
加入频道
调用 joinChannel
可以加入频道。
参数:
channelName
:频道名称,只有输入相同的频道才能进行通信。token
:权限密钥,项目启动了权限密钥功能,加入房间必须使用Token。对安全要求高的用户,请开启该功能。uid
:用户本地ID,一般为业务用户的uid,请保持频道内该uid唯一。设置NULL,SDK会自动分配一个uid给该用户。
// 加入频道。
BOOL CArObject::JoinChannel(LPCTSTR lpChannelName, UINT nUID,LPCTSTR lpToken)
{
int nRet = 0;
#ifdef UNICODE
CHAR szChannelName[128];
::WideCharToMultiByte(CP_UTF8, 0, lpChannelName, -1, szChannelName, 128, NULL, NULL);
char szToken[128];
::WideCharToMultiByte(CP_UTF8, 0, lpToken, -1, szToken, 128, NULL, NULL);
if(0 == _tcslen(lpToken))
nRet = m_lpArEngine->joinChannel(NULL, szChannelName, NULL, nUID);
else
nRet = m_lpArEngine->joinChannel(szToken, szChannelName, NULL, nUID);
#else
if(0 == _tcslen(lpToken))
nRet = m_lpArEngine->joinChannel(NULL, lpChannelName, NULL, nUID);
else
nRet = m_lpArEngine->joinChannel(lpToken, lpChannelName, NULL, nUID);
#endif
if (nRet == 0)
m_strChannelName = lpChannelName;
return nRet == 0 ? TRUE : FALSE;
}
观看远端视频流
anyRTC SDK 并不会默认拉取远端的视频流,当房间里有用户上行视频数据时,频道里的其他用户可以通过 IRtcEngineEventHandler 中的 OnFirstRemoteVideoDecoded
回调获知该用户的 uid
。之后,即可调用 setupRemoteVideo 方法来显示该用户的视频画面。
// SDK 接收到第一帧远端视频并成功解码时,会触发该回调。
// 在该回调中调用 setupRemoteVideo 方法设置远端视图。
LRESULT CArTutorialDlg::OnFirstRemoteVideoDecoded(WPARAM wParam, LPARAM lParam)
{
LPAGE_FIRST_REMOTE_VIDEO_DECODED lpData = (LPAGE_FIRST_REMOTE_VIDEO_DECODED)wParam;
VideoCanvas vc;
vc.renderMode = RENDER_MODE_FIT;
vc.uid = lpData->uid;
vc.view = m_wndRemote.GetSafeHwnd();
// 设置远端视图。
m_lpArObject->GetEngine()->setupRemoteVideo(vc);
delete lpData;
return 0;
}
退出频道
调用 leaveChannel 方法退出频道。不论当前是否还在通话中,调用该方法会把音频通话相关的所有资源释放掉。
BOOL CArObject::LeaveChannel()
{
m_lpArEngine->stopPreview();
// 离开频道。
int nRet = m_lpArEngine->leaveChannel();
return nRet == 0 ? TRUE : FALSE;
}
void CArObject::CloseArObject()
{
if(m_lpArEngine != NULL)
// 释放 IRtcEngine 对象。
m_lpArEngine->release();
if(m_lpArObject != NULL)
delete m_lpArObject;
m_lpArEngine = NULL;
m_lpArObject = NULL;
}
开发注意事项
在收发音视频流,或者频道操作前,需要确保已经成功加入频道。