基于 Agora SDK 实现 Windows 端的多人视频互动(基于3.6.2版本)
本文介绍如何通过 Agora SDK 在 Windows 平台快速实现互动直播。互动直播和实时通话的区别就在于,直播频道的用户有角色之分。你可以将角色设置为主播或者观众,其中主播可以收、发流,观众只能收流。
Demo 体验
Agora 在 GitHub 上提供一个开源的实时音视频通话示例项目 OpenLive-Windows。在实现相关功能前,你可以下载并查看源代码:https://github.com/AgoraIO/Basic-Video-Broadcasting/tree/master/OpenLive-Windows-MFC
前提条件
Microsoft Visual Studio 2017 或以上版本
支持 Windows 7 或以上版本的 Windows 设备
有效的 Agora 账户(免费注册)
如果你的网络环境部署了防火墙,请根据声网文档中心的「应用企业防火墙限制」打开相关端口。
设置开发环境
本节介绍如何创建项目,并将 Agora SDK 集成至你的项目中。
创建 Windows 项目
参考以下步骤创建一个 Windows 项目。若已有 Windows 项目,直接查看集成 SDK。
1.打开 Microsoft Visual Studio 并点击新建项目。
2.进入新建项目窗口,选择项目类型为 MFC 应用程序,输入项目名称,选择项目存储路径,并点击确认。
3.进入MFC 应用程序窗口,选择应用程序类型为基于对话框,并点击完成。
集成 SDK
参考以下步骤将 Agora SDK 集成到你的项目中。
1.配置项目文件
根据应用场景,从 SDK 下载获取最新 SDK,解压并打开。
打开已下载的 SDK 文件,并将其中的 sdk 文件夹复制到你的项目文件夹下。
2.配置项目属性
在解决方案资源管理器窗口中,右击项目名称并点击属性进行以下配置,配置完成后点击确定。
进入 C/C++ > 常规 > 附加包含目录菜单,点击编辑,并在弹出窗口选择解压的libs/include。
进入链接器 > 常规 > 附加库目录菜单,点击编辑,并在弹出窗口中解压的libs/x86或libs/x86_64。
进入链接器 > 输入 > 附加依赖项菜单,点击编辑,并在弹出窗口中解压的 agora_rtc_sdk.lib。
实现音视频直播
本节介绍如何实现音视频直播。视频直播的 API 使用时序见下图:
1. 创建用户界面
为直观地体验音视频通话,需根据应用场景创建用户界面(UI)。若项目中已有用户界面,直接查看初始化 IRtcEngine。
如果你想实现一个视频直播,推荐在 UI 上添加以下控件:
主播视频窗口
离开频道按钮
当你使用示例项目中的 UI 设计时,你将会看到如下界面:
2. 初始化 IRtcEngine
在调用其他 Agora API 前,需要创建并初始化 IRtcEngine 对象。
你需要在该步骤中填入项目的 App ID。请参考如下步骤在控制台创建 Agora 项目并获取 App ID。
1.登录控制台,点击左侧导航栏的项目管理图标。
2.点击创建,按照屏幕提示设置项目名,选择一种鉴权机制,然后点击提交。
3.在项目管理页面,你可以获取该项目的 App ID。
调用 createAgoraRtcEngine
和 initialize
方法,传入获取到的 App ID,即可初始化 IRtcEngine
。 你也可以根据需求,在初始化时实现其他功能。如注册用户加入频道和离开频道的回调(在AgoraObject.h中声明)。
// 在主播调用 joinChannel 方法后,此回调会报告加入频道的主播信息。
BOOL JoinChannel(LPCTSTR lpChannelName, UINT nUID = 0, LPCSTR lpDynamicKey = NULL);
// 在主播调用 leaveChannel 方法后,此回调会报告离开频道的主播信息。
BOOL LeaveCahnnel();
//静音本地音频
BOOL MuteLocalAudio(BOOL bMuted = TRUE);
BOOL IsLocalAudioMuted();
//静音所有远端音频
BOOL MuteAllRemoteAudio(BOOL bMuted = TRUE);
BOOL IsAllRemoteAudioMuted();
//静音本地视频
BOOL MuteLocalVideo(BOOL bMuted = TRUE);
BOOL IsLocalVideoMuted();
//静音所有远端视频
BOOL MuteAllRemoteVideo(BOOL bMuted = TRUE);
BOOL IsAllRemoteVideoMuted();
BOOL IsAllRemoteVideoMuted();
3. 设置频道模式
初始化结束后,调用 setChannelProfile
方法,将频道模式设为直播。
一个 IRtcEngine 只能使用一种频道模式。如果想切换为其他模式,需要先调用 release
方法释放当前的 IRtcEngine 实例,然后调用 createAgoraRtcEngine
和 initialize
方法创建一个新实例,再调用 setChannelProfile
设置新的频道模式。
BOOL SetChannelProfile(BOOL bBroadcastMode);
BOOL IsBroadcastMode();
4. 设置用户角色
直播频道有两种用户角色:主播和观众,其中默认的角色为观众。设置频道模式为直播后,你可以在 App 中参考如下步骤设置用户角色:
让用户选择自己的角色是主播还是观众
调用
setClientRole
方法,然后使用用户选择的角色进行传参
注意,直播频道内的用户,只能看到主播的画面、听到主播的声音。加入频道后,如果你想切换用户角色,也可以调用 setClientRole
方法。
//在AgoraObject.h中声明
BOOL SetClientRole(CLIENT_ROLE_TYPE role, LPCSTR lpPermissionKey = NULL);
int GetClientRole() { return m_nRoleType; };
//在AgoraObject.cpp实现
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);
}
5. 设置本地视图
如果你想实现一个语音直播,可以直接查看加入频道。
成功初始化 IRtcEngine 对象后,需要在加入频道前设置本地视图,以便主播在直播中看到本地图像。参考以下步骤设置本地视图(OpenLiveDig.cpp):
调用
enableVideo
方法启用视频模块。调用
setupLocalVideo
方法设置本地视图。
// 启用视频模块。
CAgoraObject::GetAgoraObject()->EnableVideo(TRUE);
// 设置本地视图。
VideoCanvas vc;
vc.uid = 0;
vc.view = m_dlgVideo.GetLocalVideoWnd();
vc.renderMode = RENDER_MODE_TYPE::RENDER_MODE_FIT;
//cancel setVideoProfile bitrate since version 2.1.0
int nVideoSolution = m_dlgSetup.GetVideoSolution();
//
VideoEncoderConfiguration config;
config.bitrate = m_dlgSetup.GetBirate();
config.frameRate = (FRAME_RATE)m_dlgSetup.GetFPS();
SIZE resolution = m_dlgSetup.GetVideoResolution();
config.dimensions.width = resolution.cx;
config.dimensions.height = resolution.cy;
lpRtcEngine->setVideoEncoderConfiguration(config);
//
m_dlgVideo.SetWindowText(strChannelName);
lpRtcEngine->setupLocalVideo(vc);
lpRtcEngine->startPreview();
6. 加入频道
完成设置角色和本地视图后(视频直播场景),你就可以调用 joinChannel
方法加入频道。你需要在该方法中传入如下参数:
channelName
: 传入能标识频道的频道 ID。输入频道 ID 相同的用户会进入同一个频道。token:传入能标识用户角色和权限的 Token。可设为如下一个值:若项目已启用 App 证书,请使用 Token。
NULL
临时 Token。临时 Token 服务有效期为 24 小时。你可以在控制台里生成一个临时 Token,详见获取临时 Token。
在你的服务器端生成的 Token。在安全要求高的场景下,我们推荐你使用此种方式生成的 Token,详见生成 Token。
uid
: 本地用户的 ID。数据类型为整型,且频道内每个用户的uid
必须是唯一的。若将uid
设为 0,则 SDK 会自动分配一个uid
,并在onJoinChannelSuccess
回调中报告。
更多的参数设置注意事项请在声网文档中心查找并参考 joinChannel
接口中的参数描述。
// 加入频道。
std::string token = lpAgoraObject->GetToken();
lpAgoraObject->JoinChannel(strChannelName, 0, token.length() > 0 ? token.c_str() : NULL);
7. 设置远端视图
视频直播中,不论你是主播还是观众,都应该看到频道中的所有主播。在加入频道后,可通过调用 setupRemoteVideo
方法设置远端主播的视图。
远端主播成功加入频道后,SDK 会触发 onFirstRemoteVideoDecoded
回调,该回调中会包含这个主播的 uid
信息。在该回调中调用 setupRemoteVideo
方法,传入获取到的 uid
,设置该主播的视图(AGEngineEventHandler.h)。
// 在引擎收到第一帧远端视频流并解码成功时,会触发此回调(AGEngineEventHandler.cpp)。
void CAGEngineEventHandler::onFirstRemoteVideoDecoded(uid_t uid, int width, int height, int elapsed)
{
LPAGE_FIRST_REMOTE_VIDEO_DECODED lpData = new AGE_FIRST_REMOTE_VIDEO_DECODED;
lpData->uid = uid;
lpData->width = width;
lpData->height = height;
lpData->elapsed = elapsed;
if(m_hMainWnd != NULL)
::PostMessage(m_hMainWnd, WM_MSGID(EID_FIRST_REMOTE_VIDEO_DECODED), (WPARAM)lpData, 0);
}
8. 离开频道
根据场景需要,如结束通话、关闭 App 或 App 切换至后台时,调用 leaveChannel
离开当前通话频道。
BOOL CAgoraObject::LeaveCahnnel()
{
m_lpAgoraEngine->stopPreview();
int nRet = m_lpAgoraEngine->leaveChannel();
m_nSelfUID = 0;
bJoinedChannel = false;
return nRet == 0 ? TRUE : FALSE;
}
//关闭引擎
void CAgoraObject::CloseAgoraObject()
{
if(m_lpAgoraEngine != NULL)
m_lpAgoraEngine->release(); if(m_lpAgoraObject != NULL)
delete m_lpAgoraObject;
m_lpAgoraEngine = NULL;
m_lpAgoraObject = NULL;
示例代码
你可以在 OpenLive-Windows 示例代码中查看完整的源码和代码逻辑,本文使用的是C++的MFC项目。
github:https://github.com/AgoraIO/Basic-Video-Broadcasting/tree/master/OpenLive-Windows-MFC
运行项目
在 Windows 设备中运行该项目。当成功开始视频直播时,主播可以看到自己的画面;观众可以看到主播的画面(当前配置为Debug模式,x64系统)。
//打开界面
//测试摄像头
//开始直播,厚码
基于 Agora SDK 实现 Windows 端的多人视频互动(基于3.6.2版本)的更多相关文章
- [原创] 【2014.12.02更新网盘链接】基于EasySysprep4.1的 Windows 7 x86/x64 『视频』封装
[原创] [2014.12.02更新网盘链接]基于EasySysprep4.1的 Windows 7 x86/x64 『视频』封装 joinlidong 发表于 2014-11-29 14:25:50 ...
- 如何基于 ZEGO SDK 实现 Windows 一对一音视频聊天应用
互联网发展至今,实时视频和语音通话越来越被大众所依赖. 今天,我们将会继续介绍如何基于ZEGO SDK实现音视频通话功能,前两篇文章分别介绍了Android,Flutter平台的实现方式,感兴趣的小伙 ...
- 基于C#和Asp.NET MVC开发GPS部标视频监控平台
基于C#和Asp.NET MVC开发GPS部标监控平台 目前整理了基于.NET技术的部标平台开发文章,可以参考: 1.部标Jt808协议模拟终端的设计和开发 2.C#版的808GPS服务器开发-> ...
- 最简单的基于FFmpeg的移动端例子:IOS 视频转码器
===================================================== 最简单的基于FFmpeg的移动端例子系列文章列表: 最简单的基于FFmpeg的移动端例子:A ...
- 用C/C++开发基于VLC SDK的视频播放器
在windows系统如果开发万能播放器,一般都是基本DirectShow来开发,开发也很简单,但缺点也很多,一个文件格式是否能够播放完全取决于你 是否安装了正确的解析器和解码器,即使现在有了万能解器安 ...
- 最简单的基于FFmpeg的移动端例子:IOS 视频解码器-保存
===================================================== 最简单的基于FFmpeg的移动端例子系列文章列表: 最简单的基于FFmpeg的移动端例子:A ...
- Redis的Windows端开发连接Linux端以及相应的代码实现
在Windows端开发连接需要进行配置文件的配置: 在redis.conf配置文件中 将protected-mode yes,修改为protected-mode no:不保护redis # By de ...
- 关于基于Linphone的视频通话Android端开发过程中遇到的问题
关于基于Linphone的视频通话Android端开发过程中遇到的问题 运用开源项目Linphone的SDK进行开发,由于是小组进行开发,我主要负责的是界面部分. 由于当时是初学Android开发,对 ...
- 基于FFMPEG SDK流媒体开发1---解码媒体文件流信息
近期项目涉及到流媒体等开发,因为有过开发经验深知其难度所在,没办法仅仅能又一次拾起,最新版的SDK被改的一塌糊涂,只是大体的开发思路都是一样的,看多少书查多少资料都无用,一步一步的编写代码 才是学好的 ...
- 基于Tcp穿越的Windows远程桌面(远程桌面管理工具)
基于Tcp穿越的Windows远程桌面(远程桌面管理工具) 1.<C# WinForm 跨线程访问控件(实用简洁写法)> 2.<基于.NET环境,C#语言 实现 ...
随机推荐
- HTML实战:个人信息登记表
效果展示: 代码示例: <!DOCTYPE html> <html lang="en"> <head> <meta charset=&qu ...
- Excel Vlookup用法和常见报错#REF! #Value!
VLOOKUP(E2,$A$2:$C$5,2,FALSE) E2 为选中查找的条件 $A$2:$C$5 1为需要查找的区域,这个区域一般是固定的,所以要加上$符号 2这个区域可以在前面加上SHEET2 ...
- 什么是spring框架
一bai.概念:1. spring是开源的轻量级框架2 spring核心主要两部分:(1)aop:面向切面编程,扩展功能不是修改源代码实现(2)ioc:控制反转,- 比如有一个类,在类里面有方法(不是 ...
- Webpack解析与讲解
一.什么是Webpack? 一个基于node.js的前端模块化/预处理/扁平化处理器. 二.为什么要使用Webpack? 解决业务代码中的各种依赖,模块加载,静态文件引入问题(重复依赖/强依赖,阻塞加 ...
- 在开启hadoop时候报错:localhost: Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password).
此时 ssh localhost也会失败 原因是秘钥没有给自己, 运行ssh-copy-id -i ~/.ssh/id_rsa.pub root@localhost 即可解决.
- 关于js数组方法filter()
1. filter() 都是数组方法,这个方法和forEach()的方法的区别又是什么呢? 2. 先说结论 filter() 和 forEach() 都是遍历数组的方法,甚至它们匿名函数的形参都是一样 ...
- eclipse project is missing required java project
eclipse project is missing required java project eclipse版本: 2022-03 这情况就是maven包出了问题 具体的说不上 看我的解决方法: ...
- CentOS7安装 Redis5 单实例
1.下载redis下载地址在:redis.io比如把Redis安装到/usr/local/soft/ cd /usr/local/soft/ wget http://download.redis.io ...
- 3vue
阻止冒泡 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF- ...
- C++11:初始化列表
在老版本的C++中,我们可以比较方便得对结构体.数组等对象利用{}进行初始化,而类变量的初始化则取决于构造函数的形式,例如: struct A { int a, b, c; }; class Foo ...