本文介绍如何通过声网 SDK 快速实现视频互动直播。
互动直播和实时通话的区别就在于,直播频道的用户有角色之分。你可以将角色设置为主播或者观众,其中主播可以收、发流,观众只能收流。
声网在 GitHub 上提供开源的视频直播示例项目 OpenLive-Windows 和 OpenLive-Windows-MFC。在实现相关功能前,你可以下载并查看源代码。
本节介绍如何创建项目,并将声网 SDK 集成至你的项目中。
参考以下步骤创建一个 Windows 项目。若已有 Windows 项目,直接查看集成 SDK。
参考以下步骤将声网视频 SDK 集成到你的项目中。
1. 配置项目文件
根据应用场景,从 SDK 下载获取最新 SDK,解压并打开。
根据你的开发环境将下载包中的 x86 或 x86_64 文件夹复制到你的项目文件夹下。
2. 配置项目属性
在解决方案资源管理器窗口中,右击项目名称并点击属性进行以下配置,配置完成后点击确定。
进入 C/C++ > 常规 > 附加包含目录菜单,点击编辑,并在弹出窗口中输入 $(SolutionDir)include。
进入链接器 > 常规 > 附加库目录菜单,点击编辑,并在弹出窗口中输入 $(SolutionDir)。
进入链接器 > 输入 > 附加依赖项菜单,点击编辑,并在弹出窗口中输入 agora_rtc_sdk.lib。
本节介绍如何实现视频直播。视频直播的 API 使用时序见下图:
为直观地体验视频通话,需根据应用场景创建用户界面(UI)。若项目中已有用户界面,直接查看初始化 IRtcEngine。
如果你想实现一个视频直播,推荐在 UI 上添加以下控件:
当你使用示例项目中的 UI 设计时,你将会看到如下界面:
在调用其他声网 API 前,需要创建并初始化 IRtcEngine
对象。
你需要在该步骤中填入项目的 App ID。请参考开始使用声网平台在控制台创建声网项目并获取 App ID。
调用 createAgoraRtcEngine
和 initialize
方法,传入获取到的 App ID,即可初始化 IRtcEngine
。
你也可以根据需求,在初始化时实现其他功能,如注册用户加入频道和离开频道的回调。
// 创建实例。
m_lpAgoraEngine = createAgoraRtcEngine();
RtcEngineContext ctx;
// 添加注册回调和事件。
ctx.eventHandler = &m_engineEventHandler;
// 输入你的 App ID。
ctx.appId = "YourAppID";
// 初始化 IRtcEngine。
m_lpAgoraEngine->initialize(ctx);
// 继承 IRtcEngineEventHandler 类中的回调与事件。
class CAGEngineEventHandler :
public IRtcEngineEventHandler
{
public:
CAGEngineEventHandler();
~CAGEngineEventHandler();
void setMainWnd(HWND wnd);
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;
};
初始化结束后,调用 setChannelProfile
方法,将频道场景设为直播。
一个 IRtcEngine 只能使用一种频道场景。如果想切换为其他模式,需要先调用 release
方法释放当前的 IRtcEngine 实例,然后调用 createAgoraRtcEngine
和 initialize
方法创建一个新实例,再调用 setChannelProfile
设置新的频道场景。
// 设置频道场景为直播。
m_lpAgoraEngine->setChannelProfile(CHANNEL_PROFILE_LIVE_BROADCASTING);
直播频道有两种用户角色:主播和观众,其中默认的角色为观众。设置频道场景为直播后,你可以在 App 中参考如下步骤设置用户角色:
setClientRole
方法,然后使用用户选择的角色进行传参注意,直播频道内的用户,只能看到主播的画面、听到主播的声音。加入频道后,如果你想切换用户角色,也可以调用 setClientRole
方法。
BOOL CAgoraObject::SetClientRole(CLIENT_ROLE_TYPE role, LPCSTR lpPermissionKey)
{
// 设置用户角色。
int nRet = m_lpAgoraEngine->setClientRole(role);
m_nRoleType = role;
return nRet == 0 ? TRUE : FALSE;
}
// 创建选择用户角色的对话框。
void CEnterChannelDlg::OnCbnSelchangeCmbRole()
{
int nSel = m_ctrRole.GetCurSel();
if (nSel == 0)
CAgoraObject::GetAgoraObject()->SetClientRole(CLIENT_ROLE_BROADCASTER);
else
CAgoraObject::GetAgoraObject()->SetClientRole(CLIENT_ROLE_AUDIENCE);
}
成功初始化 IRtcEngine
对象后,需要在加入频道前设置本地视图,以便主播在直播中看到本地图像。参考以下步骤设置本地视图:
enableVideo
方法启用视频模块。setupLocalVideo
方法设置本地视图。// 启用视频模块。
m_lpAgoraEngine->enableVideo();
// 设置本地视图。
VideoCanvas vc;
vc.uid = 0;
vc.view = hVideoWnd;
vc.renderMode = RENDER_MODE_TYPE::RENDER_MODE_HIDDEN;
m_lpAgoraEngine->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, LPCSTR lpDynamicKey)
{
int nRet = 0;
LPCSTR lpStreamInfo = "{\"owner\":true,\"width\":640,\"height\":480,\"bitrate\":500}";
#ifdef UNICODE
CHAR szChannelName[128];
::WideCharToMultiByte(CP_ACP, 0, lpChannelName, -1, szChannelName, 128, NULL, NULL);
nRet = m_lpAgoraEngine->joinChannel(lpDynamicKey, szChannelName, lpStreamInfo, nUID);
#else
nRet = m_lpAgoraEngine->joinChannel(lpDynamicKey, lpChannelName, lpStreamInfo, nUID);
#endif
if (nRet == 0)
m_strChannelName = lpChannelName;
return nRet == 0 ? TRUE : FALSE;
}
视频直播中,不论你是主播还是观众,都应该看到频道中的所有主播。在加入频道后,可通过调用 setupRemoteVideo
方法设置远端主播的视图。
远端主播成功加入频道后,SDK 会触发 onUserJoined
回调,该回调中会包含这个主播的 uid
信息。在该回调中调用 setupRemoteVideo
方法,传入获取到的 uid
,设置该主播的视图。
// 远端主播成功加入频道时,会触发该回调。
// 收到该回调后,需立即调用 setupRemoteVideo 设置远端主播的视图。
void CAGEngineEventHandler::onUserJoined(uid_t uid, int elapsed)
{
LPAGE_USER_JOINED lpData = new AGE_USER_JOINED;
lpData->uid = uid;
lpData->elapsed = elapsed;
if(m_hMainWnd != NULL)
::PostMessage(m_hMainWnd, WM_MSGID(EID_USER_JOINED), (WPARAM)lpData, 0);
}
VideoCanvas canvas;
canvas.renderMode = RENDER_MODE_FIT;
POSITION pos = m_listWndInfo.GetHeadPosition();
......
AGVIDEO_WNDINFO &agvWndInfo = m_listWndInfo.GetNext(pos);
canvas.uid = agvWndInfo.nUID;
canvas.view = m_wndVideo[nIndex].GetSafeHwnd();
agvWndInfo.nIndex = nIndex;
// 设置远端视图。
CAgoraObject::GetEngine()->setupRemoteVideo(canvas);
根据场景需要,如结束通话、关闭 App 或 App 切换至后台时,调用 leaveChannel
离开当前通话频道。
BOOL CAgoraObject::LeaveCahnnel()
{
m_lpAgoraEngine->stopPreview();
// 离开频道。
int nRet = m_lpAgoraEngine->leaveChannel();
m_nSelfUID = 0;
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 设备中运行该项目。当成功开始视频直播时,主播可以看到自己的画面;观众可以看到主播的画面。