Unity
本文以实现音视频通话为例,结合 SDK API 和示例代码,介绍如何快速接入。
环境要求
Pano SDK 支持 Unity 2017.x (LTS) 及更新的版本。
导入SDK
请到 下载中心 下载 Pano Unity SDK 压缩包并将其解压。
- 将 libs 目录下的 Android, iOS, macOS, x86, x86_64 目录复制到项目的 Assets 目录中,例如:Assets/PanoRtc/Plugins/。
- 将 libs 目录下的 Scripts 目录复制到项目的 Assets 目录中,例如:Assets/PanoRtc/。
通过 using PanoRtcGaming;
导入 SDK 文件来调用其中接口。
初始化
通过 new RtcEngine(RtcEngineConfig config)
方法创建并初始化 RtcEngine
实例。
RtcEngineConfig config = new RtcEngineConfig();
config.appId = "..."; // 替换为你的应用ID
mRtcEngine = new RtcEngine(config);
请登录 Pano控制台,点击左侧导航 应用管理 ,查看应用ID(即
appId
)。
注册通知
通过 RtcEngine
实例的相应方法来注册回调通知。
注意:必须尽早注册通知,以免错过某些通知。
mRtcEngine.OnChannelJoinConfirm += new OnChannelJoinConfirmCallback(this.OnChannelJoinConfirm);
mRtcEngine.OnChannelLeaveIndication += new OnChannelLeaveIndicationCallback(this.OnChannelLeaveIndication);
...
private void OnChannelJoinConfirm(ResultCode result)
{
// 处理 OnChannelJoinConfirm 通知
}
private void OnChannelLeaveIndication(ResultCode result)
{
// 处理 OnChannelLeaveIndication 通知
}
- 完整的回调方法介绍,请查看
IRtcEngine
中的接口事件(event)。- 为结合介绍 SDK 接口,本文会提供部分 示例代码 中的片段,请开发者注意根据实际情况调整。
获取视频采集设备
通过 RtcEngine
实例的 GetVideoDeviceManager
方法获取视频设备管理器(IVideoDeviceManager
)。
通过 IVideoDeviceManager
的 EnumerateCaptureDevices
方法枚举视频采集设备(结果将通过 OnEnumerateDeviceCallback
回调返回)。
mVideoDeviceManager = mRtcEngine.GetVideoDeviceManager();
mVideoDeviceManager.OnEnumerateCaptureDevices += new OnEnumerateDeviceCallback(this.OnEnumerateCaptureDevices);
mVideoDeviceManager.EnumerateCaptureDevices();
...
private void OnEnumerateCaptureDevices(string deviceName, string deviceId)
{
// 此处获取视频采集设备信息
}
本地预览
通过 IVideoDeviceManager
的 StartPreview
方法开启本地摄像头预览。
/* Pano Unity SDK 支持两种视频渲染方式:RawImage 和 Renderer
RawImage (RawImageVideoSurface) 适用于渲染 UI - Raw Image
Renderer (RendererVideoSurface) 适用于渲染 3D Object
*/
private IVideoDataConsumer localSurface;
// 此处演示创建一个名称为 LocalView 的 Raw Image,以 RawImage 方式渲染
localSurface = GameObject.Find("LocalView").AddComponent<RawImageVideoSurface>();
// 此处演示创建一个名称为 LocalView 的 Cube,以 Renderer 方式渲染
// localSurface = GameObject.Find("LocalView").AddComponent<RendererVideoSurface>();
...
ResultCode result = mVideoDeviceManager.StartPreview(deviceId, localSurface, VideoProfileType.HD720P);
- 如果设置的分辨率高于摄像头支持的最大分辨率,则自动降低为摄像头支持的最大分辨率。
- 如果不需要在 加入频道 前进行本地预览,可以不调用此接口。
加入频道
加入频道
通过 RtcEngine
实例的 JoinChannel
方法加入频道。
RtcChannelConfig config = new RtcChannelConfig();
// mode 频道模式:MODE_1V1 一对一模式,MODE_MEETING 多人模式
// 如果有 Web 端参与,或者需要进行直播/录制,请设置为 MODE_MEETING
config.mode = ChannelMode.MODE_MEETING;
config.serviceFlags = Constants.CHANNEL_SERVICE_MEDIA; // 频道标志(目前仅支持音视频)
config.subscribeAudioAll = true; // 自动订阅音频,可以配置为 false 来主动订阅音频
config.userName = "..."; // 设置用户名(请替换为实际值,下同)
string TOKEN = "...";
string CHANNEL_ID = "...";
UInt64 USER_ID = ...;
ResultCode result = mRtcEngine.JoinChannel(TOKEN, CHANNEL_ID, USER_ID, config);
if (result != ResultCode.OK){
// 加入失败,请根据 QResult 进行处理
}
自己加入频道的通知
调用 JoinChannel
方法后,将触发 OnChannelJoinConfirm
通知。
mRtcEngine.OnChannelJoinConfirm += new OnChannelJoinConfirmCallback(this.OnChannelJoinConfirm);
private void OnChannelJoinConfirm(ResultCode result)
{
// ResultCode 表示自己加入频道的结果
}
"加入频道"接口返回的
ResultCode
仅表示调用该接口的结果,而"自己加入频道的通知"返回的ResultCode
表示和服务器交互后的结果。
也就是说当"自己加入频道的通知"返回OK
才表示加入频道成功。
其他用户加入频道的通知
其他用户加入频道后,将触发 OnUserJoinIndication
通知。
mRtcEngine.OnUserJoinIndication += new OnUserJoinIndicationCallback(this.OnUserJoinIndication);
private void OnUserJoinIndication(UInt64 userId, string userName)
{
// 其他用户加入频道的通知。userId 和 userName 都是该用户在 加入频道 时传入的
// 此时可以将其加入到与会者列表中
}
倒计时通知
加入频道后,如果存在倒计时限制,将触发 OnChannelCountDown
通知。
mRtcEngine.OnChannelCountDown += new OnChannelCountDownCallback(this.OnChannelCountDown);
private void OnChannelCountDown(UInt32 remain){
// 频道倒计时通知,单位:秒;请保存用于展示倒计时,此回调仅在加入频道后回调一次
}
- 已实名认证,并且使用正式token,Pano不限制频道时长
- 未实名认证,或者使用临时token,最大频道时长为 30 分钟
操作视频
如果你不使用视频功能,请忽略本节,直接跳转到下一节:操作声音。
发送本地视频
通过 RtcEngine
实例的 StartVideo
方法发送本地视频。
// 调用此方法后,其他用户才能看到你的画面;请在 自己加入频道的通知 返回成功后再调用
// 此处示例发送分辨率 1280 x 720,实际使用请按需配置
ResultCode result = mRtcEngine.StartVideo(localSurface, VideoProfileType.HD720P);
- 调用此方法,会触发
OnVideoStartResult
回调。- 发送本地视频 时设置的分辨率表示期望的发送分辨率,实际过程中可能会因硬件支持情况、网络情况和订阅情况触发 SDK 自动调整而降低(后文会介绍订阅)。
- 如果在 发送本地视频 前调用了 本地预览 接口,可以先调用 停止本地预览(
IVideoDeviceManager
-StopPreview
) 接口再 发送本地视频,避免重复显示。
停止发送本地视频
通过 RtcEngine
实例的 StopVideo
方法停止发送本地视频。
// 调用此方法后,其他用户将看不到你的画面
// 会同时停止向 StartVideo 方法设置的渲染位置传递视频数据
ResultCode result = mRtcEngine.StopVideo();
其他用户开启视频的通知
当其他用户发送视频时,将触发 OnUserVideoStart
通知。
mRtcEngine.OnUserVideoStart += new OnUserVideoStartCallback(this.OnUserVideoStart);
private void OnUserVideoStart(UInt64 userId, VideoProfileType maxProfile)
{
// maxProfile 表示该用户的最大可发送分辨率
// 取决于 摄像头支持的最大分辨率 和 设置的发送分辨率 这两个值中的较小值
}
订阅其他用户的视频
通过 RtcEngine
实例的 SubscribeVideo
方法订阅其他用户的视频。
// 请在收到 其他用户开启视频的通知 后,再调用订阅;返回 OK 表示接口调用成功,否则表示失败
// 此处示例订阅分辨率 1280 x 720,实际使用请按需配置
ResultCode result = mRtcEngine.SubscribeVideo(userId, remoteSurface, VideoProfileType.HD720P);
- Pano采用订阅模式来接收视频,参与者之间需要相互订阅,才可以看到彼此的视频画面。
- 默认 正式token 最多可以订阅 10 路视频,临时token 最多可以订阅 3 路视频。
- 如果订阅失败,会触发
OnUserVideoSubscribe
通知。
视频首帧的通知
当自己发送或收到其他用户第一个视频帧时,将触发 onFirstVideoFrameRendered
通知。
mRtcEngine.OnFirstVideoFrameRendered += new OnFirstVideoFrameRenderedCallback(this.OnFirstVideoFrameRendered);
private void OnFirstVideoFrameRendered(UInt64 userId)
{
// 第一个视频帧通知,可以开始显示视频画面
}
取消订阅其他用户的视频
通过 RtcEngine
实例的 UnsubscribeVideo
方法取消订阅其他用户的视频。
ResultCode result = mRtcEngine.UnsubscribeVideo(userId); // 调用此方法后,你将看不到该用户的画面
当其他用户停止视频或者离开频道的时候,将被自动取消订阅。
操作声音
发送本地声音
通过 RtcEngine
实例的 StartAudio
方法发送本地声音。
// 调用此方法后,其他用户才能听到你的声音;请在加入频道成功后再调用
ResultCode result = mRtcEngine.StartAudio();
调用此方法,会触发
OnAudioStartResult
回调。
停止发送本地声音
通过 RtcEngine
实例的 StopAudio
方法停止发送本地声音。
// 调用此方法后,其他用户将听不到你的声音
// 不影响你接收其他用户的声音
// 可以调用 发送本地声音 接口重新发送
ResultCode result = mRtcEngine.StopAudio();
静音麦克风
通过 RtcEngine
实例的 MuteAudio
方法静音本地麦克风。
ResultCode result = mRtcEngine.MuteAudio(); // 调用此方法后,其他用户将听不到你的麦克风的声音
停止发送本地声音(
StopAudio
) 和 静音本地麦克风(MuteAudio
) 这两个接口都可以将自己静音(不让其他用户听到你的声音)。它们的区别在于:
1 "停止发送本地声音"会断开音频通道连接(同时停止发送麦克风和伴音的声音,会取消其他用户订阅你的声音,如需重建连接需要消耗时间)
2 "静音本地麦克风"会发送静音包(不影响伴音发送,不影响订阅关系,静音包数据量很小,临时静音建议使用此方式,取消静音能够迅速恢复发送声音)
取消静音麦克风
通过 RtcEngine
实例的 UnmuteAudio
方法取消静音本地麦克风。
// 静音麦克风后,需要取消静音,其他用户才能听到你的麦克风的声音
ResultCode result = mRtcEngine.UnmuteAudio();
其他用户开启声音的通知
当其他用户发送声音时,将触发 OnUserAudioStart
通知。
mRtcEngine.OnUserAudioStart += new OnUserAudioStartCallback(this.OnUserAudioStart);
private void OnUserAudioStart(ulong userId)
{
// 其他用户开启声音的通知
}
订阅其他用户的声音
如果在 加入频道 时,配置了自动订阅音频(例如:config.subscribeAudioAll = true
),则开发者无需再主动订阅其他用户的声音。否则,需要通过 RtcEngine
实例的 SubscribeAudio
方法订阅其他用户的声音。
// 如果 加入频道 时配置了自动订阅音频,则无需调用此接口
// 请在收到 其他用户开启声音的通知 后,再调用订阅
ResultCode result = mRtcEngine.SubscribeAudio(userId);
- 如果希望在通话过程中,不收听某位与会者,或者不收听所有其他与会者,请在加入频道时,设置不自动订阅音频;随后按需订阅或取消订阅某位或所有其他与会者。
- 如果订阅失败,会触发
OnUserAudioSubscribe
通知。
收到其他用户声音的通知
当收到其他用户的声音时,将触发 OnFirstAudioDataReceived
通知。
mRtcEngine.OnFirstAudioDataReceived += new OnFirstAudioDataReceivedCallback(this.OnFirstAudioDataReceived);
private void OnFirstAudioDataReceived(ulong userId)
{
// 收到其他用户的首个声音数据包
}
取消订阅其他用户的声音
通过 RtcEngine
实例的 UnsubscribeAudio
方法取消订阅其他用户的声音。
ResultCode result = mRtcEngine.UnsubscribeAudio(userId);// 调用此方法后,你将听不到该用户的声音
当其他用户停止声音或者离开频道的时候,将被自动取消订阅。
离开频道
离开频道
通过 RtcEngine
实例的 LeaveChannel
方法离开频道。
ResultCode result = mRtcEngine.LeaveChannel();
注意:此接口为同步接口;调用此接口主动离开频道,自己不会收到
OnChannelLeaveIndication
回调。
其他用户离开频道的通知
其他用户离开频道后,将触发 OnUserLeaveIndication
通知。
mRtcEngine.OnUserLeaveIndication += new OnUserLeaveIndicationCallback(this.OnUserLeaveIndication);
private void OnUserLeaveIndication(ulong userId, UserLeaveReason reason)
{
// 可将其从与会者列表中移除
}
释放资源
通过 Destroy
方法销毁 RtcEngine
实例。
mRtcEngine.Destroy();
示例代码
为方便开发者了解丰富的接口使用方式,我们还提供示例代码,包含在 SDK 包的 samples/PanoUnityDemo 目录中,使用方法请查看其中的 README 文件。