Pano开发者中心
  • 文档中心
  • 下载中心

iOS (Objective-C)

本文以实现视频通话为例,结合 SDK API 和示例代码,介绍如何快速接入。

如需查看完整 SDK API 列表,请点击左侧导航 SDK API 部分。

导入SDK

  • 请到 下载中心 下载 iOS SDK压缩包。
  • 将其解压,iOS 目录下有两个子目录:
    • Release-iphoneall:支持真机和模拟器的SDK版本,仅用于开发调试,无法发布到App Store。
    • Release-iphoneos:只支持真机的SDK版本,可以发布到App Store。
  • 按需选择相应的目录,将其中的 PanoRtc.framework 复制到项目目录中。
  • 打开 Xcode,定位到 TARGETS - General - Frameworks, Libraries, and Embedded Content,添加 PanoRtc.framework,将 Embed 属性设置为 Embed & Sign。
  • 通过 #import "PanoRtc/PanoRtcEngineKit.h" 导入 SDK 文件来调用其中接口。

配置权限

在 app 的 info.plist 中添加以下两项内容:

  • Privacy - Microphone Usage Description: Value 填写 app 需要使用麦克风的提示信息
  • Privacy - Camera Usage Description: Value 填写 app 需要使用摄像头的提示信息

注册通知

通过实现 PanoRtcEngineDelegate 协议的回调方法来处理 Pano SDK 返回的通知。

@interface ChannelViewController () <PanoRtcEngineDelegate>
...
@end

@implementation ChannelViewController
- (void)onChannelJoinConfirm:(PanoResult)result {
    // 自己加入频道的通知
}

- (void)onChannelLeaveIndication:(PanoResult)result {
    // 自己离开频道的通知
}
...
@end
  • 完整的回调方法介绍,请查看 PanoRtcEngineDelegate 协议。
  • 为结合介绍 SDK 接口,本文会提供部分 示例代码 中的片段,请开发者注意根据实际情况调整。

初始化

通过 PanoRtcEngineKit 的 + engineWithConfig:delegate: 方法初始化实例。

PanoRtcEngineConfig * engineConfig = [[PanoRtcEngineConfig alloc] init];
engineConfig.appId = @""; // 替换为你的应用ID
engineConfig.rtcServer = @"api.pano.video"; // PANO服务器地址
self.engineKit = [PanoRtcEngineKit engineWithConfig:engineConfig delegate:self];

请登录 Pano控制台,点击左侧导航 应用管理 ,查看应用ID(即 appId)。

本地预览

通过 PanoRtcEngineKit 实例的 - startPreviewWithView:config: 方法或 - startPreviewWithDelegate:profile: 方法开启本地摄像头预览。
两者的区别在于:前者随带渲染视图,后者随带外置渲染器。后文类似接口不再重复介绍。

PanoRtcRenderConfig * config = [[PanoRtcRenderConfig alloc] init];
config.profileType = kPanoProfileHD720P; // 分辨率:1280 x 720
config.scalingMode = kPanoScalingCropFill; // 保持宽高比裁剪填充
config.mirror = [self.engineKit isFrontCamera]; // 是否启用镜像,一般前置摄像头需要镜像
[self.engineKit startPreviewWithView:self.previewView config:config];
  • 如果设置的分辨率高于摄像头支持的最大分辨率,则自动降低为摄像头支持的最大分辨率。
  • 如果不需要在 加入频道 前进行本地预览,可以不调用此接口。

切换摄像头

通过 PanoRtcEngineKit 实例的 - isFrontCamera 方法判断是否是前置摄像头,通过 - switchCamera 方法切换摄像头。

if ([self.engineKit isFrontCamera] == NO) {
    [self.engineKit switchCamera]; // 此方法会同时影响本地预览和发送出去的视频画面
}

加入频道

加入频道

通过 PanoRtcEngineKit 实例的 - joinChannelWithToken:channelId:userId:config: 方法加入频道。

PanoRtcChannelConfig * channelConfig = [[PanoRtcChannelConfig alloc] init];
channelConfig.mode = kPanoChannelMeeting; // 频道模式
// serviceFlags 频道标志:音视频 | 白板 (按位或)
// channelConfig.serviceFlags = kPanoChannelServiceMedia | kPanoChannelServiceWhiteboard;
channelConfig.serviceFlags = kPanoChannelServiceMedia; // 只使用音视频
channelConfig.subscribeAudioAll = YES; // 自动订阅音频
channelConfig.userName = @""; // 设置用户名
PanoResult result = [self.engineKit joinChannelWithToken:@""
                                               channelId:@""
                                                  userId:userId
                                                  config:channelConfig];
if (result != kPanoResultOK) {
    // 加入失败,请根据 PanoResult 进行处理
}
  • 另请参考 名词解释 了解 channelId、token、userId、userName 的作用。
  • 可以使用 临时token 来进行临时测试。

自己加入频道的通知

调用 - joinChannelWithToken:channelId:userId:config: 方法后,将触发 - onChannelJoinConfirm: 通知。

- (void)onChannelJoinConfirm:(PanoResult)result {
    // PanoResult 表示自己加入频道的结果
}

"加入频道"接口返回的 PanoResult 仅表示调用该接口的结果,而"自己加入频道的通知"返回的 PanoResult 表示和服务器交互后的结果。
也就是说当"自己加入频道的通知"返回 kPanoResultOK 才表示加入频道成功。

其他用户加入频道的通知

其他用户加入频道后,将触发 - onUserJoinIndication:withName: 通知。

- (void)onUserJoinIndication:(UInt64)userId
                    withName:(NSString * _Nullable)userName {
    // 其他用户加入频道的通知。userId 和 userName 都是该用户在 加入频道 时传入的
    // 此时可以将其加入到与会者列表中
}

倒计时通知

加入频道后,如果存在倒计时限制,将触发 - onChannelCountDown: 通知。

- (void)onChannelCountDown:(UInt32)remain {
    // 频道倒计时通知,单位:秒;请保存用于展示倒计时,此回调仅在加入频道后回调一次
}
  • 已实名认证,并且使用正式token,Pano不限制频道时长
  • 未实名认证,或者使用临时token,最大频道时长为 30 分钟

操作视频

发送本地视频

通过 PanoRtcEngineKit 实例的 - startVideoWithView:config: 方法或 - startVideoWithDelegate:profile: 方法发送本地视频。

// 调用此方法后,其他用户才能看到你的画面;请在 自己加入频道的通知 返回成功后再调用
PanoRtcRenderConfig * renderConfig = [[PanoRtcRenderConfig alloc] init];
renderConfig.profileType = kPanoProfileHD720P;
renderConfig.scalingMode = kPanoScalingCropFill;
renderConfig.mirror = YES;
// profileType 会同时影响发送和渲染,scalingMode 和 mirror 只影响渲染不影响发送
[self.engineKit startVideoWithView:self.localView config:renderConfig];
  • 发送本地视频 接口设置的分辨率表示期望的发送分辨率,实际过程中可能会因硬件支持情况、网络情况和订阅情况触发 SDK 自动调整而降低(后文会介绍订阅)。
  • 如果在 发送本地视频 前调用了 本地预览 接口,可以先调用 停止本地预览(- stopPreview) 接口再 发送本地视频,避免重复显示。

停止发送本地视频

通过 PanoRtcEngineKit 实例的 - stopVideo 方法停止发送本地视频。

// 调用此方法后,其他用户将看不到你的画面
// 会同时停止向 发送本地视频 方法设置的渲染视图或外置渲染器传递视频数据
[self.engineKit stopVideo];
  • 当 本地预览 和 发送本地视频 接口设置不同的 PanoVideoProfileType 时,预览分辨率会自动调整为和和实际的发送分辨率一致。当 停止发送本地视频 后,预览的分辨率会恢复为设置的分辨率。
  • 当然,前提条件仍然是摄像头支持相应的分辨率,否则会降低为摄像头支持的最大分辨率。
    后文同理不再重复介绍。

其他用户开启视频的通知

当其他用户发送视频时,将触发 - onUserVideoStart:withMaxProfile: 通知。

- (void)onUserVideoStart:(UInt64)userId
          withMaxProfile:(PanoVideoProfileType)maxProfile {
    // maxProfile 表示该用户的最大可发送分辨率
    // 取决于 摄像头支持的最大分辨率 和 设置的发送分辨率 这两个值中的较小值。
    // 即:maxProfile = min{摄像头支持的最大分辨率, 设置的发送分辨率}
    // 可以订阅低于 maxProfile 的 PanoVideoProfileType ,以节省带宽、流量和费用
    // 例如,当应用场景需要同时展示多个远端小画面时,可以向远端订阅一个较低的分辨率
}

订阅其他用户的视频

通过 PanoRtcEngineKit 实例的 - subscribeVideo:withView:config: 方法或 - subscribeVideo:withDelegate:profile: 方法订阅其他用户的视频。

// 请在收到 其他用户开启视频的通知 后,再调用订阅;返回 kPanoResultOK 表示接口调用成功,否则表示失败
PanoRtcRenderConfig * config = [[PanoRtcRenderConfig alloc] init];
config.profileType = kPanoProfileHD720P;
config.scalingMode = kPanoScalingCropFill;
[self.engineKit subscribeVideo:userId withView:view config:config];
  • Pano采用订阅模式来接收视频,参与者之间需要相互订阅,才可以看到彼此的视频画面。
  • 默认 正式token 最多可以订阅 6 路视频,临时token 最多可以订阅 3 路视频。
  • 使用 PanoRtcVideoStreamManager 的开发者,请换用其 - subscribeVideo:stream:view:config: 或 - subscribeVideo:stream:delegate:profile: 方法来订阅其他用户的视频流。

订阅视频结果通知

当订阅其他用户的视频后,会触发 - onUserVideoSubscribe:withResult: 通知。

- (void)onUserVideoSubscribe:(UInt64)userId
                  withResult:(PanoSubscribeResult)result {
    // 处理订阅视频结果通知,kPanoSubscribeSuccess 表示成功
}
  • 订阅其他用户的视频 接口返回的 PanoResult 仅表示调用该接口的结果,而 订阅视频结果通知 返回的 PanoSubscribeResult 表示和服务器交互后的结果。
    也就是说,订阅视频结果通知 返回 kPanoSubscribeSuccess 才表示订阅成功。
  • 如果重复调用 订阅其他用户的视频 接口,只会在第一次调用时触发 订阅视频结果通知。如果取消订阅再重新订阅,视为第一次调用,可正常触发一次 订阅视频结果通知。

收到其他用户视频的通知

当收到其他用户的视频时,将触发 - onFirstVideoDataReceived: 通知。

- (void)onFirstVideoDataReceived:(UInt64)userId {
    // 收到其他用户的首个视频数据包
}

取消订阅其他用户的视频

通过 PanoRtcEngineKit 实例的 - unsubscribeVideo: 方法取消订阅其他用户的视频。

[self.engineKit unsubscribeVideo:userId]; // 调用此方法后,你将看不到该用户的画面
  • 当其他用户停止视频或者离开频道的时候,将被自动取消订阅。
  • 使用 PanoRtcVideoStreamManager 的开发者,请换用其 - unsubscribeVideo:stream: 方法来取消订阅。

操作声音

发送本地声音

通过 PanoRtcEngineKit 实例的 - startAudio 方法发送本地声音。

[self.engineKit startAudio]; // 调用此方法后,其他用户才能听到你的声音;请在加入频道成功后再调用

停止发送本地声音

通过 PanoRtcEngineKit 实例的 - stopAudio 方法停止发送本地声音。

// 调用此方法后,其他用户将听不到你的声音
// 不影响你接收其他用户的声音
// 可以调用 发送本地声音 接口重新发送
[self.engineKit stopAudio];

有三种方式将自己静音(不让其他用户听到你的声音):1 停止发送本地声音,2 静音本地麦克风,3 静音本地麦克风(系统层操作)
它们的区别在于:
1 "停止发送本地声音"会断开音频通道连接(同时停止发送麦克风和伴音的声音,会取消其他用户订阅你的声音,如需重建连接需要消耗时间)
2 "静音本地麦克风"会发送静音包(不影响伴音发送,不影响订阅关系,临时静音建议使用此方式,取消静音能够迅速恢复发送声音)
3 "静音本地麦克风(系统层操作)"会调用系统接口设置底层硬件状态,一般情况不建议使用,因此本文不介绍该接口

静音

通过 PanoRtcEngineKit 实例的 - muteAudio 方法静音本地麦克风。

[self.engineKit muteAudio]; // 调用此方法后,其他用户将听不到你的声音

取消静音

通过 PanoRtcEngineKit 实例的 - unmuteAudio 方法取消静音本地麦克风。

[self.engineKit unmuteAudio]; // 静音后,需要取消静音,其他用户才能听到你的声音

其他用户开启声音的通知

当其他用户发送声音时,将触发 - onUserAudioStart: 通知。

- (void)onUserAudioStart:(UInt64)userId {
    ...
}

订阅其他用户的声音

如果在 加入频道 时,配置了自动订阅音频(例如:channelConfig.subscribeAudioAll = YES),则开发者无需再主动订阅其他用户的声音。否则,需要通过 PanoRtcEngineKit 实例的 - subscribeAudio: 方法订阅其他用户的声音。

// 如果 加入频道 时配置了自动订阅音频,则无需调用此接口
// 请在收到 其他用户开启声音的通知 后,再调用订阅
[self.engineKit subscribeAudio:userId];
  • 如果希望在通话过程中,不收听某位与会者,或者不收听所有其他与会者,请在加入频道时,设置不自动订阅音频;随后按需订阅或取消订阅某位或所有其他与会者。

订阅声音结果通知

当主动订阅其他用户的声音后,会触发 - onUserAudioSubscribe:withResult: 通知。

- (void)onUserAudioSubscribe:(UInt64)userId
                  withResult:(PanoSubscribeResult)result {
    // 处理订阅声音结果通知,kPanoSubscribeSuccess 表示成功
}
  • 订阅其他用户的声音 接口返回的 PanoResult 仅表示调用该接口的结果,而 订阅声音结果通知 返回的 PanoSubscribeResult 表示和服务器交互后的结果。
    也就是说,订阅声音结果通知 返回 kPanoSubscribeSuccess 才表示订阅成功。
  • 如果配置了自动订阅音频,则不会触发此通知。

收到其他用户声音的通知

当收到其他用户的声音时,将触发 - onFirstAudioDataReceived: 通知。

- (void)onFirstAudioDataReceived:(UInt64)userId {
    // 收到其他用户的首个声音数据包
}

取消订阅其他用户的声音

通过 PanoRtcEngineKit 实例的 - unsubscribeAudio: 方法取消订阅其他用户的声音。

[self.engineKit unsubscribeAudio:userId]; // 调用此方法后,你将听不到该用户的声音

当其他用户停止声音或者离开频道的时候,将被自动取消订阅。

离开频道

离开频道

通过 PanoRtcEngineKit 实例的 - leaveChannel 方法离开频道。

[self.engineKit leaveChannel];

其他用户离开频道的通知

其他用户离开频道后,将触发 - onUserLeaveIndication:withReason: 通知。

- (void)onUserLeaveIndication:(UInt64)userId
                   withReason:(PanoUserLeaveReason)reason {
    // 可将其从与会者列表中移除
}

至此,iOS 快速接入已介绍完毕。

SDK API 指南

本文仅介绍接入Pano iOS SDK实现视频通话的基本流程和接口。
实际场景需要结合使用更多接口,请 点此查看 API 列表。

示例代码

为方便开发者了解丰富的接口使用方式,我们还提供示例代码,请 体验参考。

Last updated on 12/7/2020
  • 导入SDK
  • 配置权限
  • 注册通知
  • 初始化
  • 本地预览
  • 切换摄像头
  • 加入频道
    • 加入频道
    • 自己加入频道的通知
    • 其他用户加入频道的通知
    • 倒计时通知
  • 操作视频
    • 发送本地视频
    • 停止发送本地视频
    • 其他用户开启视频的通知
    • 订阅其他用户的视频
    • 订阅视频结果通知
    • 收到其他用户视频的通知
    • 取消订阅其他用户的视频
  • 操作声音
    • 发送本地声音
    • 停止发送本地声音
    • 静音
    • 取消静音
    • 其他用户开启声音的通知
    • 订阅其他用户的声音
    • 订阅声音结果通知
    • 收到其他用户声音的通知
    • 取消订阅其他用户的声音
  • 离开频道
    • 离开频道
    • 其他用户离开频道的通知
  • SDK API 指南
  • 示例代码
浙ICP备20002645号-1 Copyright ©2020 拍乐云. All Rights Reserved