本文介绍如何使用声网视频 SDK 快速实现视频通话。
声网在 GitHub 上提供开源的实时视频通话示例项目 Agora-Windows-Tutorial-1to1 和 GroupVideoCall-Windows-MFC。在实现相关功能前,你可以下载并查看源代码。
如果你是第一次使用声网的服务,我们推荐观看下面的视频,了解关于声网服务的基本信息以及如何快速跑通示例项目。
本节介绍如何创建项目,并将声网视频 SDK 集成至你的项目中。
参考以下步骤创建一个 Windows 项目。若已有 Windows 项目,直接查看集成 SDK。
参考以下步骤将声网视频 SDK 集成到你的项目中。
1. 配置项目文件
根据应用场景,从 SDK 下载获取最新 SDK,解压并打开。
根据你的开发环境将下载包中的 x86 或 x86_64 文件夹复制到你的项目文件夹下。
2. 配置项目属性
在解决方案资源管理器窗口中,右击项目名称并点击属性进行以下配置,配置完成后点击确定。
进入 C/C++ > 常规 > 附加包含目录菜单,点击编辑,并在弹出窗口中输入 $(SolutionDir)include。
进入链接器 > 常规 > 附加库目录菜单,点击编辑,并在弹出窗口中输入 $(SolutionDir)。
进入链接器 > 输入 > 附加依赖项菜单,点击编辑,并在弹出窗口中输入 agora_rtc_sdk.lib。
本节介绍如何实现视频通话。视频通话的 API 调用时序见下图:
根据场景需要,为你的项目创建视频通话的用户界面。若已有用户界面,可以直接查看初始化 IRtcEngine。
如果你想实现一个视频通话,我们推荐你添加如下 UI 元素:
当你使用示例项目中的 UI 设计时,你将会看到如下界面:
在调用其他声网 API 前,需要创建并初始化 IRtcEngine 对象。
你需要在该步骤中填入项目的 App ID。请参考开始使用声网平台在控制台创建声网项目并获取 App ID。
调用 createAgoraRtcEngine
和 initialize
方法,传入获取到的 App ID,即可初始化 IRtcEngine
。
你还可以根据场景需要,在初始化时注册想要监听的回调事件,如注册用户加入频道和离开频道的回调。
CAgoraObject *CAgoraObject::GetAgoraObject(LPCTSTR lpAppId)
{
if (m_lpAgoraObject == NULL)
m_lpAgoraObject = new CAgoraObject();
if (m_lpAgoraEngine == NULL)
// 创建实例。
m_lpAgoraEngine = (IRtcEngine *)createAgoraRtcEngine();
if (lpAppId == NULL)
return m_lpAgoraObject;
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_lpAgoraEngine->initialize(ctx);
return m_lpAgoraObject;
}
// 继承 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);
// 注册 onUserJoined 回调。
// 远端用户成功加入频道时,会触发该回调。
// 收到该回调后,需立即调用 setupRemoteVideo 设置远端用户的视图。
virtual void onUserJoined(uid_t uid, int elapsed) override;
// 注册 onUserOffline 回调。
// 远端用户离开频道或掉线时,会触发该回调。
virtual void onUserOffline(uid_t uid, USER_OFFLINE_REASON_TYPE reason);
private:
HWND m_hMainWnd;
};
成功初始化 IRtcEngine 对象后,需要在加入频道前设置本地视图,以便在通话中看到本地图像。参考以下步骤设置本地视图:
enableVideo
方法启用视频模块。setupLocalVideo
方法设置本地视图。// 启用视频模块。
m_lpAgoraObject->GetEngine()->enableVideo();
// 设置本地视图。
VideoCanvas vc;
vc.uid = 0;
vc.view = m_wndLocal.GetSafeHwnd();
vc.renderMode = RENDER_MODE_FIT;
m_lpAgoraObject->GetEngine()->setupLocalVideo(vc);
完成初始化和设置本地视图后,你就可以调用 joinChannel
方法加入频道。你需要在该方法中传入如下参数:
channelName
: 传入能标识频道的频道 ID。输入频道 ID 相同的用户会进入同一个频道。
token
:传入用于鉴权的 Token,可设为如下一个值:
token
设为 ""。uid
: 本地用户的 ID。数据类型为整型,且频道内每个用户的 uid
必须是唯一的。若将 uid
设为 0,则 SDK 会自动分配一个 uid
,并在 onJoinChannelSuccess
回调中报告。mute
方法实现。更多的参数设置注意事项请参考 joinChannel
接口中的参数描述。
// 加入频道。
BOOL CAgoraObject::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_lpAgoraEngine->joinChannel(NULL, szChannelName, NULL, nUID);
else
nRet = m_lpAgoraEngine->joinChannel(szToken, szChannelName, NULL, nUID);
#else
if(0 == _tcslen(lpToken))
nRet = m_lpAgoraEngine->joinChannel(NULL, lpChannelName, NULL, nUID);
else
nRet = m_lpAgoraEngine->joinChannel(lpToken, lpChannelName, NULL, nUID);
#endif
if (nRet == 0)
m_strChannelName = lpChannelName;
return nRet == 0 ? TRUE : FALSE;
}
视频通话中,通常你也需要看到其他用户。在加入频道后,可通过调用 setupRemoteVideo
方法设置远端用户的视图。
远端用户成功加入频道后,SDK 会触发 onUserJoined
回调,该回调中会包含这个远端用户的 uid
信息。在该回调中调用 setupRemoteVideo
方法,传入获取到的 uid
,设置远端用户的视图。
// 远端用户成功加入频道时,会触发该回调。
// 收到该回调后,需立即调用 setupRemoteVideo 设置远端用户的视图。
LRESULT CAgoraTutorialDlg::OnEIDUserJoined(WPARAM wParam, LPARAM lParam)
{
LPAGE_USER_JOINED lpData = (LPAGE_USER_JOINED)wParam;
VideoCanvas vc;
vc.renderMode = RENDER_MODE_FIT;
vc.uid = lpData->uid;
vc.view = m_wndRemote.GetSafeHwnd();
// 设置远端视图。
m_lpAgoraObject->GetEngine()->setupRemoteVideo(vc);
delete lpData;
return 0;
}
根据场景需要,如结束通话、关闭 App 或 App 切换至后台时,调用 leaveChannel
离开当前通话频道。
BOOL CAgoraObject::LeaveChannel()
{
m_lpAgoraEngine->stopPreview();
// 离开频道。
int nRet = m_lpAgoraEngine->leaveChannel();
return nRet == 0 ? TRUE : FALSE;
}
void CAgoraObject::CloseAgoraObject()
{
if(m_lpAgoraEngine != NULL)
// 释放 IRtcEngine 对象。
m_lpAgoraEngine->release();
if(m_lpAgoraObject != NULL)
delete m_lpAgoraObject;
m_lpAgoraEngine = NULL;
m_lpAgoraObject = NULL;
}
你可以在 Windows 设备中运行此项目。当你成功开始视频通话时,你可以同时看到本地和远端的视频。