集成概览

本文将介绍如何通过AICallKit SDK集成音视频智能体到您的iOS应用中。

环境要求

  • Xcode 16.0 及以上版本,推荐使用最新正式版本

  • CocoaPods 1.9.3 及以上版本

  • 准备 iOS 11.0 及以上版本的真机

业务流程

image

您的App通过AppServer(你的业务服务器)获取RTC Token,便可调用call(config)方法进入通话,在通话过程中,可以调用AICallKitAPI实现智能体的实时字幕、打断等交互功能。AICallKit依赖于实时音视频能力,因此在内部已实现AliVCSDK_ARTC SDK的相关功能。如果您的业务场景还需要用到直播与点播能力,可以使用音视频终端组合SDK,例如AliVCSDK_StandardAliVCSDK_InteractiveLive,具体组合方式,请参考SDK选择与下载

集成SDK

target '你的Target' do

  # 依赖实时音视频能力,引入AliVCSDK_ARTC或AliVCSDK_Standard或AliVCSDK_InteractiveLive
  pod 'AliVCSDK_ARTC', '~> 7.4.0'
  # 引入AICallKit SDK
  pod 'ARTCAICallKit', '~> 2.7.0'
  
  ...

end
说明

ARTC SDK版本请到SDK下载/集成最新适配版本号。

工程配置

  • 添加麦克风与摄像头权限,打开工程info.Plist,添加NSMicrophoneUsageDescriptionNSCameraUsageDescription权限。

  • 打开工程设置,在Signing & Capabilities中开启Background Modes,强烈推荐开启后台模式,否则在进入后台后无法继续通话,这时候在您的APP中需要调用结束通话接口。

SDK开发指南

步骤一:检查APP麦克风、摄像头权限

检查APP麦克风、摄像头权限,如未授权,则弹框交给用户进行授权。业务App需要您自行实现, 参考代码请参见AVDeviceAuth.h

步骤二:创建&初始化引擎

创建&初始化ARTCAICallEngine引擎,示例代码如下:

// 创建engine实例
let engine = ARTCAICallEngineFactory.createEngine()
let agentType: ARTCAICallAgentType

// 初始化engine实例
public func setup() {
    // 设置回调
    self.engine.delegate = self

    // 如果是数字人类型,则需要配置数字人显示的视图配置
    if self.agentType == .AvatarAgent {
        let agentViewConfig = ARTCAICallViewConfig(view: self.avatarAgentView)
        self.engine.setAgentViewConfig(viewConfig: agentViewConfig)
    }
    // 如果是视觉理解类型,则需要配置本地视频预览配置
    else if self.agentType == .VisionAgent {
        let cameraViewConfig = ARTCAICallViewConfig(view: self.cameraView)
        self.engine.setLocalViewConfig(viewConfig: cameraViewConfig)
    }
    // 如果是视频通话类型,则需要配置数字人显示的视图配置+本地视频预览配置
    else if self.agentType == .VideoAgent {
        let agentViewConfig = ARTCAICallViewConfig(view: self.avatarAgentView)
        self.engine.setAgentViewConfig(viewConfig: agentViewConfig)

        let cameraViewConfig = ARTCAICallViewConfig(view: self.cameraView)
        self.engine.setLocalViewConfig(viewConfig: cameraViewConfig)
    }
}

步骤三:实现回调方法

实现引擎回调,按需实现回调方法。引擎回调接口详情,请参见API接口详情

// 回调处理(仅示例不分核心的回调操作)
public func onErrorOccurs(code: ARTCAICallErrorCode) {
    // 发生了错误
    self.engine.handup()
}

public func onCallBegin() {
    // 通话开始
}

public func onCallEnd() {
    // 通话结束
}

public func onAgentStateChanged(state: ARTCAICallAgentState) {
    // 智能体状态改变
}

public func onUserSubtitleNotify(text: String, isSentenceEnd: Bool, sentenceId: Int) {
    // 用户提问被智能体识别结果的通知
}

public func onVoiceAgentSubtitleNotify(text: String, isSentenceEnd: Bool, userAsrSentenceId: Int) {
    // 智能体回答结果通知
}

public func onVoiceIdChanged(voiceId: String) {
    // 当前通话的音色发生了改变
}

public func onVoiceInterrupted(enable: Bool) {
    // 当前通话的语音打断是否启用
}

步骤四:创建并初始化ARTCAICallConfig

ARTCAICallConfig详情,请参见ARTCAICallConfig

let callConfig = ARTCAICallConfig()
callConfig.agentId = "xxx"             // 智能体Id
callConfig.agentType = self.agentType  // 智能体类型
callConfig.userId = "xxx"              // 推荐使用你的App登录后的用户id
callConfig.region = "xx-xxx"           // 智能体服务所在的区域
callConfig.userJoinToken = "xxxxxxxxx" // RTC Token

// 针对视觉理解&视频通话,需要设置视频配置
// 这里frameRate设置为5,需要根据控制台上的智能体的抽帧率(一般为2)进行调整,最大不建议超过15fps
// bitrate: frameRate超过10可以设置为512
if self.config.agentType == .VisionAgent{
    callConfig.videoConfig = ARTCAICallVideoConfig(frameRate: 5, bitrate: 340, useFrontCameraDefault: false)
}
if self.config.agentType == .VideoAgent {
    callConfig.videoConfig = ARTCAICallVideoConfig(frameRate: 5, bitrate: 340, useFrontCameraDefault: true)
}
                

地域名称

Region Id

华东1(杭州)

cn-hangzhou

华东2(上海)

cn-shanghai

华北2(北京)

cn-beijing

华南1(深圳)

cn-shenzhen

新加坡

ap-southeast-1

userJoinToken需要您获取RTC Token,详情请参见生成ARTC鉴权Token

步骤五:发起智能体呼叫

调用call(config)接口发起智能体呼叫。

// 启动智能体后,开始通话
public func start() {
    let callConfig = ...   // 参考上面代码生成callConfig对象
    if self.engine.call(config: callConfig) {
        // API被成功调用
    }
}


//接通后,会触发以下回调
public func onCallBegin() {
    // 通话开始
}

步骤六:通话中的业务实现

在开启通话后,您可以根据您的业务需求处理字幕、打断智能体讲话等。详细内容,请参见功能实现

步骤七:通话结束,挂断智能体通话

调用handup()接口,挂断智能体通话。

public func handup() {
    self.engine.handup()
}