Windows (C++)
本文以实现视频通话为例,结合 SDK API 和示例代码,介绍如何快速接入。
如需查看完整 SDK API 列表,请点击左侧导航 SDK API 部分。
导入SDK
- 请到 下载中心 下载 Windows SDK压缩包。
- 将其解压,Windows 目录下有 api 和 lib 两个子目录。
lib 目录下包含 x64 和 x86 两种架构,64位程序请使用 x64 目录,32位程序请使用 x86 目录。 - 将 api 目录和 lib/x64 或 lib/x86 目录放到项目目录中。
- 在 Visual Studio "解决方案资源管理器"中,右击项目名称 > 点击"属性"进行如下配置:
- 配置属性 > C/C++ > 常规 > 附加包含目录,编辑添加上述 api 目录
- 配置属性 > 链接器 > 常规 > 附加库目录,编辑添加上述 lib/x64 或 lib/x86 目录
- 配置属性 > 链接器 > 输入 > 附加依赖项,编辑添加上述 lib/x64 或 lib/x86 目录中的 PanoRtc.lib 文件
注册通知
通过继承 RtcEngine::Callback
类,重写回调接口来处理 Pano SDK 返回的通知。
class RtcTester : public panortc::RtcEngine::Callback
{
...
public: // RtcEngine::Callback
void onChannelJoinConfirm(panortc::QResult result) override;
void onChannelLeaveIndication(panortc::QResult result) override;
...
}
- 完整的回调方法介绍,请查看 RtcEngine::Callback 接口类。
- 为结合介绍 SDK 接口,本文会提供部分 示例代码 中的片段,请开发者注意根据实际情况调整。
初始化
通过 RtcEngine
的 initialize
方法初始化实例。
const std::string kAppId = ""; // 替换为你的应用ID
const std::string kPanoServer = "api.pano.video"; // PANO服务器地址
RtcEngine::Configuration config{ this, kAppId.c_str(), kPanoServer.c_str(), AudioAecType::Default, false };
auto ret = rtcEngine_->initialize(config);
请登录 Pano控制台,点击左侧导航 应用管理 ,查看应用ID(即
appId
)。
获取视频采集设备
通过 RtcEngine
实例的 getVideoDeviceManager
方法获取视频设备管理器 VideoDeviceManager
对象。
通过 VideoDeviceManager
的 enumerateCaptureDevices
方法枚举视频采集设备。
auto *videoDeviceMgr = rtcEngine_->getVideoDeviceManager();
videoDeviceMgr->enumerateCaptureDevices([] (
void *context,
const char deviceName[kMaxDeviceNameLength],
const char deviceId[kMaxDeviceIDLength]) {
...
}, &cb);
本地预览
通过 VideoDeviceManager
的 startPreview
方法开启本地摄像头预览。
startPreview
有两个重载方法,参数类型不同,一个传入数据接收漕和 VideoProfileType
,一个传入显示窗口和 RenderConfig
(下面示例代码采用此方法;后文类似接口不再重复介绍)。
HWND hWnd = previewVideoView_;
RenderConfig renderConfig;
renderConfig.profileType = VideoProfileType::HD720P; // 分辨率:1280 x 720
renderConfig.scalingMode = VideoScalingMode::CropFill; // 保持宽高比裁剪填充
renderConfig.enableMirror = true; // 启用视频镜像
videoDeviceMgr->startPreview(deviceId, hWnd, renderConfig);
- 如果设置的分辨率高于摄像头支持的最大分辨率,则自动降低为摄像头支持的最大分辨率。
- 如果不需要在 加入频道 前进行本地预览,可以不调用此接口。
加入频道
加入频道
通过 RtcEngine
实例的 joinChannel
方法加入频道。
RtcEngine::ChannelConfiguration channelConfig;
channelConfig.mode = ChannelMode::Mode_Meeting; // 频道模式:多人模式
channelConfig.subscribeAudioAll = true; // 自动订阅音频
channelConfig.userName = ""; // 设置用户名
ret = rtcEngine_->joinChannel(panoToken_.c_str(), channelId_.c_str(), localUserId_, channelConfig);
if (ret != QResult::OK) {
// 加入失败,请根据 QResult 进行处理
}
自己加入频道的通知
调用 joinChannel
方法后,将触发 onChannelJoinConfirm
通知。
void RtcTester::onChannelJoinConfirm(QResult result)
{
// QResult 表示自己加入频道的结果
}
"加入频道"接口返回的
QResult
仅表示调用该接口的结果,而"自己加入频道的通知"返回的QResult
表示和服务器交互后的结果。
也就是说当"自己加入频道的通知"返回OK
才表示加入频道成功。
其他用户加入频道的通知
其他用户加入频道后,将触发 onUserJoinIndication
通知。
void RtcTester::onUserJoinIndication(uint64_t userId, const char *userName)
{
// 其他用户加入频道的通知。userId 和 userName 都是该用户在 加入频道 时传入的
// 此时可以将其加入到与会者列表中
}
倒计时通知
加入频道后,如果存在倒计时限制,将触发 onChannelCountDown
通知。
void RtcTester::onChannelCountDown(uint32_t remain)
{
// 频道倒计时通知,单位:秒;请保存用于展示倒计时,此回调仅在加入频道后回调一次
}
- 已实名认证,并且使用正式token,Pano不限制频道时长
- 未实名认证,或者使用临时token,最大频道时长为 30 分钟
操作视频
发送本地视频
通过 RtcEngine
实例的 startVideo
方法发送本地视频。
HWND hWnd = localVideoView_;
RenderConfig renderConfig;
renderConfig.profileType = VideoProfileType::HD720P; // 分辨率:1280 x 720
renderConfig.scalingMode = VideoScalingMode::CropFill; // 保持宽高比裁剪填充
renderConfig.enableMirror = true; // 启用视频镜像
// profileType 会同时影响发送和渲染,scalingMode 和 enableMirror 只影响渲染不影响发送
// 调用下面方法后,其他用户才能看到你的画面;请在 自己加入频道的通知 返回成功后再调用
rtcEngine_->startVideo(hWnd, renderConfig);
- 发送本地视频 接口设置的分辨率表示期望的发送分辨率,实际过程中可能会因硬件支持情况、网络情况和订阅情况触发 SDK 自动调整而降低(后文会介绍订阅)。
- 如果在 发送本地视频 前调用了 本地预览 接口,可以先调用 停止本地预览(
VideoDeviceManager
-stopPreview
) 接口再 发送本地视频,避免重复显示。
停止发送本地视频
通过 RtcEngine
实例的 stopVideo
方法停止发送本地视频。
// 调用此方法后,其他用户将看不到你的画面
// 会同时停止向 startVideo 方法设置的数据接收漕或显示窗口传递视频数据
rtcEngine_->stopVideo();
- 当 本地预览 和 发送本地视频 接口设置不同的
VideoProfileType
时,预览分辨率会自动调整为和和实际的发送分辨率一致。当 停止发送本地视频 后,预览的分辨率会恢复为设置的分辨率。- 当然,前提条件仍然是摄像头支持相应的分辨率,否则会降低为摄像头支持的最大分辨率。
后文同理不再重复介绍。
其他用户开启视频的通知
当其他用户发送视频时,将触发 onUserVideoStart
通知。
void RtcTester::onUserVideoStart(uint64_t userId, VideoProfileType maxProfile)
{
// maxProfile 表示该用户的最大可发送分辨率
// 取决于 摄像头支持的最大分辨率 和 设置的发送分辨率 这两个值中的较小值。
// 即:maxProfile = min{摄像头支持的最大分辨率, 设置的发送分辨率}
// 可以订阅低于 maxProfile 的 PanoVideoProfileType ,以节省带宽、流量和费用
// 例如,当应用场景需要同时展示多个远端小画面时,可以向远端订阅一个较低的分辨率
}
订阅其他用户的视频
通过 RtcEngine
实例的 subscribeVideo
方法订阅其他用户的视频。
// 请在收到 其他用户开启视频的通知 后,再调用订阅;返回 OK 表示接口调用成功,否则表示失败
RenderConfig renderConfig;
renderConfig.profileType = VideoProfileType::HD720P; // 分辨率:1280 x 720
renderConfig.scalingMode = VideoScalingMode::CropFill; // 保持宽高比裁剪填充
renderConfig.enableMirror = false;
rtcEngine_->subscribeVideo(userId, view, renderConfig);
- Pano采用订阅模式来接收视频,参与者之间需要相互订阅,才可以看到彼此的视频画面。
- 默认 正式token 最多可以订阅 6 路视频,临时token 最多可以订阅 3 路视频。
- 使用
VideoStreamManager
的开发者,请换用VideoStreamManager::subscribeVideo
方法来订阅其他用户的视频流。
订阅视频结果通知
当订阅其他用户的视频后,会触发 onUserVideoSubscribe
通知。
void RtcTester::onUserVideoSubscribe(uint64_t userId, MediaSubscribeResult result)
{
// 处理订阅视频结果通知,Success 表示成功
}
- 订阅其他用户的视频 接口返回的
QResult
仅表示调用该接口的结果,而 订阅视频结果通知 返回的MediaSubscribeResult
表示和服务器交互后的结果。
也就是说,订阅视频结果通知 返回Success
才表示订阅成功。- 如果重复调用 订阅其他用户的视频 接口,只会在第一次调用时触发 订阅视频结果通知。如果取消订阅再重新订阅,视为第一次调用,可正常触发一次 订阅视频结果通知。
收到其他用户视频的通知
当收到其他用户的视频时,将触发 onFirstVideoDataReceived
通知。
void RtcTester::onFirstVideoDataReceived(uint64_t userId)
{
// 收到其他用户的首个视频数据包
}
取消订阅其他用户的视频
通过 RtcEngine
实例的 unsubscribeVideo
方法取消订阅其他用户的视频。
rtcEngine_->unsubscribeVideo(userId); // 调用此方法后,你将看不到该用户的画面
- 当其他用户停止视频或者离开频道的时候,将被自动取消订阅。
- 使用
VideoStreamManager
的开发者,请换用VideoStreamManager::unsubscribeVideo
方法来取消订阅。
操作声音
发送本地声音
通过 RtcEngine
实例的 startAudio
方法发送本地声音。
rtcEngine_->startAudio(); // 调用此方法后,其他用户才能听到你的声音;请在加入频道成功后再调用
停止发送本地声音
通过 RtcEngine
实例的 stopAudio
方法停止发送本地声音。
// 调用此方法后,其他用户将听不到你的声音
// 不影响你接收其他用户的声音
// 可以调用 发送本地声音 接口重新发送
rtcEngine_->stopAudio();
有三种方式将自己静音(不让其他用户听到你的声音):1 停止发送本地声音,2 静音本地麦克风,3 静音本地麦克风(系统层操作)
它们的区别在于:
1 "停止发送本地声音"会断开音频通道连接(同时停止发送麦克风和伴音的声音,会取消其他用户订阅你的声音,如需重建连接需要消耗时间)
2 "静音本地麦克风"会发送静音包(不影响伴音发送,不影响订阅关系,临时静音建议使用此方式,取消静音能够迅速恢复发送声音)
3 "静音本地麦克风(系统层操作)"会调用系统接口设置底层硬件状态,一般情况不建议使用,因此本文不介绍该接口
静音
通过 RtcEngine
实例的 muteAudio
方法静音本地麦克风。
rtcEngine_->muteAudio(); // 调用此方法后,其他用户将听不到你的声音
取消静音
通过 RtcEngine
实例的 unmuteAudio
方法取消静音本地麦克风。
rtcEngine_->unmuteAudio(); // 静音后,需要取消静音,其他用户才能听到你的声音
其他用户开启声音的通知
当其他用户发送声音时,将触发 onUserAudioStart
通知。
void RtcTester::onUserAudioStart(uint64_t userId)
{
...
}
订阅其他用户的声音
如果在 加入频道 时,配置了自动订阅音频(例如:channelConfig.subscribeAudioAll = true
),则开发者无需再主动订阅其他用户的声音。否则,需要通过 RtcEngine
实例的 subscribeAudio
方法订阅其他用户的声音。
// 如果 加入频道 时配置了自动订阅音频,则无需调用此接口
// 请在收到 其他用户开启声音的通知 后,再调用订阅
rtcEngine_->subscribeAudio(userId);
- 如果希望在通话过程中,不收听某位与会者,或者不收听所有其他与会者,请在加入频道时,设置不自动订阅音频;随后按需订阅或取消订阅某位或所有其他与会者。
订阅声音结果通知
当主动订阅其他用户的声音后,会触发 onUserAudioSubscribe
通知。
void RtcTester::onUserAudioSubscribe(uint64_t userId, MediaSubscribeResult result)
{
// 处理订阅声音结果通知,Success 表示成功
}
- 订阅其他用户的声音 接口返回的
QResult
仅表示调用该接口的结果,而 订阅声音结果通知 返回的MediaSubscribeResult
表示和服务器交互后的结果。
也就是说,订阅声音结果通知 返回Success
才表示订阅成功。- 如果配置了自动订阅音频,则不会触发此通知。
收到其他用户声音的通知
当收到其他用户的声音时,将触发 onFirstAudioDataReceived
通知。
void RtcTester::onFirstAudioDataReceived(uint64_t userId)
{
// 收到其他用户的首个声音数据包
}
取消订阅其他用户的声音
通过 RtcEngine
实例的 unsubscribeAudio
方法取消订阅其他用户的声音。
rtcEngine_->unsubscribeAudio(userId); // 调用此方法后,你将听不到该用户的声音
当其他用户停止声音或者离开频道的时候,将被自动取消订阅。
离开频道
离开频道
通过 RtcEngine
实例的 leaveChannel
方法离开频道。
rtcEngine_->leaveChannel();
其他用户离开频道的通知
其他用户离开频道后,将触发 onUserLeaveIndication
通知。
void RtcTester::onUserLeaveIndication(uint64_t userId, UserLeaveReason reason)
{
// 可将其从与会者列表中移除
}
至此,Windows 快速接入已介绍完毕。
SDK API 指南
本文仅介绍接入Pano Windows SDK实现视频通话的基本流程和接口。
实际场景需要结合使用更多接口,请 点此查看 API 列表。
示例代码
为方便开发者了解丰富的接口使用方式,我们还提供示例代码,请 体验参考。