实现纯语音互动
本文介绍如何集成声网实时互动 SDK,通过少量代码从 0 开始实现一个简单的纯语音互动 App,适用于语音通话场景。
首先,你需要了解以下有关音视频实时互动的基础概念:
- 声网实时互动 SDK:由声网开发的、帮助开发者在 App 中实现实时音视频互动的 SDK。
- 频道:用于传输数据的通道,在同一个频道内的用户可以进行实时互动。
- 主播:可以在频道内发布音视频,同时也可以订阅其他主播发布的音视频。
- 观众:可以在频道内订阅音视频,不具备发布音视频权限。
更多概念详见关键概念。
下图展示在 App 中实现纯语音互动的基本工作流程:

- 所有用户调用
joinChannel
方法加入频道,并将所有用户角色都设置为主播。 - 加入频道后,所有用户都可以在频道内发布音频流,并订阅对方的音频流。
前提条件
在实现功能以前,请按照以下要求准备开发环境:
- Windows 7 或以上版本的设备。
- Microsoft Visual Studio 2017 或以上版本。
- C++ 11 或以上版本。
- 如果使用 C# 开发,还需要 .NET 桌面开发组件。
- 可以访问互联网的计算机。如果你的网络环境部署了防火墙,参考应对防火墙限制以正常使用声网服务。
- 一个有效的声网账号以及声网项目。请参考开通服务从声网控制台获得以下信息:
- App ID:声网随机生成的字符串,用于识别你的项目。
- 临时 Token:Token 也称为动态密钥,在客户端加入频道时对用户鉴权。临时 Token 的有效期为 24 小时。
建立项目
创建 Windows 项目
参考创建 C++ 控制台应用项目,在 Visual Studio 上创建一个 C++ 控制台应用项目。
集成 SDK
参考以下步骤将声网 SDK 集成到你的项目中。
- 从资源获取获取最新的 Windows SDK,解压并打开。
- 打开已下载的 SDK 文件,并将其中的
sdk
文件夹中的所有子文件夹复制到你的解决方案文件夹下。保证这些子文件夹和你的sln
文件处于同一目录。
配置项目属性
在解决方案资源管理器窗口中,右击项目名称并点击属性进行以下配置,配置完成后点击确定。
- 进入C/C++ > 常规 > 附加包含目录菜单,点击编辑,并在弹出窗口中输入
$(SolutionDir)include
。 - 进入链接器 > 常规 > 附加库目录菜单,点击编辑,并在弹出窗口中输入
$(SolutionDir)lib
。 - 进入链接器 > 输入 > 附加依赖项菜单,点击编辑,并在弹出窗口中输入
agora_rtc_sdk.dll.lib
。
在客户端实现纯语音互动
本节介绍如何使用声网音频 SDK 在你的 App 里实现纯语音互动。API 的调用时序见下图:
-
创建用户界面
为直观地体验纯语音互动,需根据应用场景创建用户界面(UI)。若项目中已有用户界面,直接查看初始化 IRtcEngine。
如果你想实现一个纯语音互动,推荐在 UI 上添加以下控件:
- 结束语音互动按钮
如下界面可供你参考:
-
初始化
IRtcEngine
在调用其他声网 API 前,需要创建并初始化
IRtcEngine
对象。调用
createAgoraRtcEngine
方法和initialize
方法并传入 App ID,初始化IRtcEngine
。你也可以根据需求,在初始化时实现其他功能,如注册用户加入频道和离开频道的回调。
C++// 创建一个 IRtcEngine 实例。
m_lpAgoraEngine = createAgoraRtcEngine();
RtcEngineContext ctx;
// 添加注册回调和事件。
ctx.eventHandler = &m_engineEventHandler;
// 输入你的 App ID。你可以在声网控制台获取你的项目的 App ID。
ctx.appId = "Your App ID";
// 初始化 IRtcEngine。
m_lpAgoraEngine->initialize(ctx);C++// 继承 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 回调。
// 远端主播成功加入频道时,会触发该回调。
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;
}; -
加入频道
设置频道场景和用户角色,并使用临时 token 加入频道。
C++void CLiveBroadcastingDlg::OnBnClickedButtonJoinchannel()
{
if (!m_rtcEngine || !m_initialize)
return;
CString strInfo;
if (!m_joinChannel) {
CString strChannelName;
m_edtChannelName.GetWindowText(strChannelName);
if (strChannelName.IsEmpty()) {
AfxMessageBox(_T("Fill channel name first"));
return;
}
ChannelMediaOptions options;
// 将频道场景设置为 LIVE_BROADCASTING
options.channelProfile = CHANNEL_PROFILE_LIVE_BROADCASTING;
// 设置用户角色为主播
options.clientRoleType = CLIENT_ROLE_TYPE(m_cmbRole.GetCurSel() + 1);
options.autoSubscribeAudio = true;
// 使用你在声网控制台生成的临时 token 加入频道,在这里传入你的项目的 Token 和频道名。
if (0 == m_rtcEngine->joinChannel(APP_TOKEN, szChannelId.c_str(), 0, options)) {
strInfo.Format(_T("join channel %s, use ChannelMediaOptions"), getCurrentTime());
m_btnJoinChannel.EnableWindow(FALSE);
}
}
else {
if (0 == m_rtcEngine->leaveChannel()) {
strInfo.Format(_T("leave channel %s"), getCurrentTime());
m_btnJoinChannel.EnableWindow(FALSE);
}
}
m_lstInfo.InsertString(m_lstInfo.GetCount(), strInfo);
} -
离开频道
根据场景需要,如结束通话、关闭 App 或 App 切换至后台时,调用
leaveChannel
离开当前通话频道。C++void CLiveBroadcastingDlg::UnInitAgora()
{
if (m_rtcEngine) {
if(m_joinChannel)
// 离开频道
m_rtcEngine->leaveChannel();
m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("leaveChannel"));
// 释放 IRtcEngine.
m_rtcEngine->release(true);
m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("release rtc engine"));
m_rtcEngine = NULL;
}
}
后续步骤
在测试或生产环境中,为保证通信安全,声网推荐从服务器中获取 Token,详情请参考使用 Token 鉴权。