# 实现相芯美颜 (/zh-CN/solutions/showroom/build/beauty/faceunity-integrate)

> For AI agents: see the complete documentation index at [llms.txt](/llms.txt).

<_PlatformTabsGroup>
<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="android" platform="android" />
## 示例项目 [#示例项目]

本文介绍如何通过声网美颜场景化 API (Beauty API) 集成相芯美颜到实时音视频互动中。声网在 GitHub 上提供开源 `BeautyAPI` 示例项目供你参考。

<Cards>
  <Card title="BeautyAPI" href="https://github.com/AgoraIO-Community/BeautyAPI" />
</Cards>

## 准备开发环境 [#准备开发环境]

### 前提条件 [#前提条件]

开始前，请确保满足以下前提条件：

- [Git](https://git-scm.com/downloads)
- [Java Development Kit](https://www.oracle.com/java/technologies/javase-downloads.html) 11
- [Android Studio](https://developer.android.com/studio/) 3.5 及以上
- Android 手机，版本 Android 5.0（API Level 21）及以上
- [开通秀场直播服务](/zh-CN/solutions/showroom/build/enable-service)
- 已联系相芯技术获取最新的美颜 SDK、美颜资源、美颜证书
- 已在项目中添加 Kotlin 插件

### 创建项目并集成 SDK [#创建项目并集成-sdk]

按照如下步骤准备开发环境：

1. 如需创建新项目，在 **Android Studio** 里，依次选择 **Phone and Tablet > Empty Activity**，创建 [Android 项目](https://developer.android.com/studio/projects/create-project)。

   :::warning[注意]
   创建项目后，**Android Studio** 会自动开始同步 gradle, 稍等片刻至同步成功后再进行下一步操作。
   :::

2. 使用 Maven Central 将声网 RTC SDK 集成到你的项目中。

   1. 在 `/Gradle Scripts/build.gradle(Project: <projectname>)` 文件中添加如下代码，添加 Maven Central 依赖：

        ```kotlin
        buildscript {
            repositories {
                ...
                mavenCentral()
            }
            ...
        }
        allprojects {
            repositories {
                ...
                mavenCentral()
            }
        }
        ```

        :::warning[注意]
        如果你的 Android 项目设置了 [dependencyResolutionManagement](https://docs.gradle.org/current/userguide/centralizing_repositories.html)，添加 Maven Central 依赖的方式可能存在差异。
        :::

   2. 在 `/Gradle Scripts/build.gradle(Module: <projectname>.app)` 文件中添加如下代码，将声网 RTC SDK 集成到你的 Android 项目中：

        ```kotlin
        // 配置相芯依赖库
        allprojects {
            repositories {
                maven {
                    url = "http://maven.faceunity.com/repository/maven-public/"
                    allowInsecureProtocol = true
                }
            }
        }

        dependencies {
            ...
            // x.y.z，请填写具体的 RTC SDK 版本号，如：4.0.0 或 4.1.0-1
            // 通过实时互动产品发版说明获取最新版本号
            implementation 'io.agora.rtc:full-sdk:x.y.z'
            // 集成相芯美颜资源
            implementation 'com.faceunity:core:8.3.0'
            implementation 'com.faceunity:model:8.3.0'
        }
        ```

3. 将相芯美颜 SDK 复制到你的项目中：请联系相芯技术支持获取美颜 SDK、美颜资源、证书等文件。下载并解压文件，然后添加到美颜项目对应的文件路径下：

    | 文件    |  项目路径   |
    |-----|-----|
    | 美妆资源：例如 `naicha.bundle` | `app/src/main/assets/beauty_faceunity/makeup`           |
    | 贴纸资源：例如 `fashi.bundle`  | `app/src/main/assets/beauty_faceunity/sticker`          |
    | 证书：`authpack.java`    | `app/src/main/java/io/agora/beauty/demo/authpack.java`  |

4. 将声网美颜场景化 API 集成到你的项目中。添加 [Android/lib_faceunity/src/main/java/io/agora/beautyapi/faceunity](https://github.com/AgoraIO-Community/BeautyAPI/tree/main/Android/lib_faceunity/src/main/java/io/agora/beautyapi/faceunity) 目录下的文件到项目中，具体文件如下：
    - `utils` 文件夹
    - `FaceUnityBeautyAPI.kt` 文件
    - `FaceUnityBeautyAPIImpl` 文件

    :::warning[注意]
    为方便后续代码升级，请不要修改你添加的这些文件的名称和路径。
    :::

5. 添加网络及设备权限。

   在 `/app/Manifests/AndroidManifest.xml` 文件中，在 `</application>` 后面添加如下权限：

   ```xml
    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.CAMERA"/>
    <uses-permission android:name="android.permission.RECORD_AUDIO"/>
    <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    <uses-permission android:name="android.permission.BLUETOOTH"/>
    <!-- 对于 Android 12.0 及以上且集成 v4.1.0 以下声网 RTC SDK 的设备，还需要添加以下权限 -->
    <uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/>
    <!-- 对于 Android 12.0 及以上设备，还需要添加以下权限 -->
    <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
    <uses-permission android:name="android.permission.BLUETOOTH_SCAN"/>
   ```

6. 在 `/Gradle Scripts/proguard-rules.pro` 文件中添加如下行，以防止声网 RTC SDK 的代码被混淆：

   ```kotlin
   -keep class io.agora.**{*;}
   -dontwarn javax.**
   -dontwarn com.google.devtools.build.android.**
   ```

## 实现美颜 [#实现美颜]

本节展示如何在直播间内实现美颜功能，参考 [API 时序图](#api-时序图)可查看总览。声网 RTC SDK 承担实时音视频的业务，相芯美颜 SDK 提供美颜功能，声网 Beauty API 封装了两个 SDK 中的 API 调用逻辑以简化你需要实现的代码逻辑。通过 Beauty API，你可以实现基础美颜功能，但是如果你还需要更丰富的美颜效果，例如贴纸、美妆风格，请直接调用美颜 SDK 中的 API。

### 1. 初始化 RtcEngine [#1-初始化-rtcengine]

调用声网 RTC SDK 中的 `create` 创建并初始化 `RtcEngine` 对象。

```kotlin
// 初始化声网 RtcEngine
private val mRtcEngine by lazy {
    RtcEngine.create(RtcEngineConfig().apply {
        mContext = applicationContext
        // 传入你从控制台获取的声网项目的 APP ID
        mAppId = BuildConfig.AGORA_APP_ID
        mEventHandler = object : IRtcEngineEventHandler() {}
    })
}
```

### 2. 初始化美颜 SDK [#2-初始化美颜-sdk]

调用相芯美颜 SDK 的 `registerFURender` 初始化 `FURenderKit` 对象，同时传入如下参数：

- `context`：Android Context（上下文）。
- `getAuth()`：`getAuth` 方法返回的鉴权字段，格式为 ByteArray。鉴权字段与本地 `authpack.java` 证书文件相关，只有验证通过后，你才能使用相芯美颜 SDK。
- `object`：事件回调。

初始化美颜 SDK 成功后，在新线程中通过 `loadAIProcessor` 加载 AI 道具。

```kotlin
object FaceUnityBeautySDK {
    private val TAG = "FaceUnityBeautySDK"

    private val fuAIKit = FUAIKit.getInstance()
    val fuRenderKit = FURenderKit.getInstance()

    // AI 道具
    private val BUNDLE_AI_FACE = "model" + File.separator + "ai_face_processor.bundle"
    private val BUNDLE_AI_HUMAN = "model" + File.separator + "ai_human_processor.bundle"

    private val workerThread = Executors.newSingleThreadExecutor()

    fun initBeauty(context: Context){
        // 设置美颜 SDK 日志
        FURenderManager.setKitDebug(FULogger.LogLevel.TRACE)
        FURenderManager.setCoreDebug(FULogger.LogLevel.ERROR)
        // 初始化美颜 SDK
        // 需传入美颜 SDK 鉴权字段并设置美颜 SDK 事件监听
        FURenderManager.registerFURender(context, getAuth(), object : OperateCallback {
            override fun onSuccess(code: Int, msg: String) {
                Log.i(TAG, "FURenderManager onSuccess -- code=$code, msg=$msg")
                if (code == OPERATE_SUCCESS_AUTH) {
                    faceunity.fuSetUseTexAsync(1)
                    // 如果初始化美颜 SDK 成功，在新线程中加载 AI 道具
                    workerThread.submit {
                        fuAIKit.loadAIProcessor(BUNDLE_AI_FACE, FUAITypeEnum.FUAITYPE_FACEPROCESSOR)
                        fuAIKit.loadAIProcessor(BUNDLE_AI_HUMAN, FUAITypeEnum.FUAITYPE_HUMAN_PROCESSOR)
                    }
                }
            }

            override fun onFail(errCode: Int, errMsg: String) {
                Log.e(TAG, "FURenderManager onFail -- code=$errCode, msg=$errMsg")
            }
        })
    }

    // 获取美颜 SDK 鉴权字段
    private fun getAuth(): ByteArray{
        val authpack = Class.forName("io.agora.beautyapi.demo.authpack")
        val aMethod = authpack.getDeclaredMethod("A")
        aMethod.isAccessible = true
        val authValue = aMethod.invoke(null) as? ByteArray
        return authValue ?: ByteArray(0)
    }
}
```

### 3. 初始化 Beauty API [#3-初始化-beauty-api]

调用 `createFaceUnityBeautyAPI` 创建 Beauty API 对象。Beauty API 对象基于 `FuRenderKit` 对象封装。

```kotlin
// 创建 Beauty API 对象
private val mFaceUnityApi by lazy {
    createFaceUnityBeautyAPI()
}
```

调用 `initialize` 初始化 Beauty API 对象。你需要在 `config` 参数中传入如下字段：

- `applicationContext`：传入 Android Context（上下文）。
- `mRtcEngine`：传入之前初始化的 `RtcEngine` 对象。
- `fuRenderKit`：传入之前初始化的 `FuRenderKit` 对象。
- `captureMode`：视频的采集模式：
    - 如果你使用声网模块采集视频，请传入 `CaptureMode.Agora`。
    - 如果自定义采集视频，请传入 `CaptureMode.Custom`。
- `cameraConfig`：设置视频镜像模式。如果在初始化 Beauty API 后你想修改镜像模式，可以调用 Beauty API 的 `updateCameraConfig`。
- `statsEnable`：是否开启美颜统计数据回调。`true` 代表开启，`false` 代表不开启。开启后，会有周期性的 `onBeautyStats` 回调事件。
- `statsDuration`：美颜统计数据回调的周期。单位为毫秒。
- `eventCallback`：你希望监听的回调事件。

```kotlin
// 初始化 Beauty API 对象
mFaceUnityApi.initialize(
    Config(
        // Android Context（上下文）
        applicationContext,
        // RtcEngine
        mRtcEngine,
        // 美颜特效管理器
        fuRenderKit,
        // 设置视频采集模式
        // CaptureMode.Agora 意味着使用声网模块采集视频
        // CaptureMode.Custom 意味着使用开发者自定义采集视频
        captureMode = if(isCustomCaptureMode) CaptureMode.Custom else CaptureMode.Agora,
        // 配置视频镜像模式
        cameraConfig = this.cameraConfig,
        // 是否开启美颜统计数据
        // 开启后，会有周期性的 onBeautyStats 回调事件
        statsEnable = true,
        // 设置美颜统计数据的统计区间为 1000 毫秒（默认）
        statsDuration = 1000,
        // 用于监听 Beauty API 的回调事件
        eventCallback = object: IEventCallback{
            override fun onBeautyStats(stats: BeautyStats) {
                Log.d(TAG, "BeautyStats stats = $stats")
            }
        }
    )
)
```

### 4. 开启美颜 [#4-开启美颜]

调用 Beauty API 的 `enable` 方法并将参数设为 `true` 开启美颜。

```kotlin
mFaceUnityApi.enable(true)
```

### 5. 开启视频采集 [#5-开启视频采集]

开发者可以使用声网模块采集视频，也可以自定义采集视频。本节介绍在这两种场景下如何开启视频采集。

#### 使用声网模块采集视频 [#使用声网模块采集视频]

使用声网模块采集视频时，你需要先调用 `RtcEngine` 类的 `enableVideo` 开启声网 RTC SDK 的视频模块，然后调用 Beauty API 的 `setupLocalVideo` 开启本地视图。

```kotlin
// 开启视频模块
mRtcEngine.enableVideo()
// 设置本地视图
mFaceUnityApi.setupLocalVideo(mBinding.localVideoView, Constants.RENDER_MODE_FIT)
```

#### 自定义视频采集 [#自定义视频采集]

使用自定义视频采集时，你需要进行如下操作：

1. 调用 `RtcEngine` 类的 `enableVideo` 开启声网 RTC SDK 的视频模块。
2. 开启自定义视频采集。可以使用声网 RTC SDK 的 API 开启视频自采集，也可以使用第三方视频自采集。如下示例代码展示通过声网 RTC SDK 的 API 进行的自定义视频采集，具体逻辑为通过 `RtcEngine` 类的 `registerVideoFrameObserver` 注册原始视频数据观测器并在其中实现 `onCaptureVideoFrame` 函数。
3. 完成视频自采集后，通过 Beauty API 的 `onFrame` 函数将外部自采集的视频数据包装成 `VideoFrame` 传入并进行处理。当处理结果不为 `SKIPPED`（忽略）时，`VideoFrame` 里的视频 Buffer 数据会被替换成美颜处理过后的数据，你可以取出处理后的 Buffer 数据传入声网 RTC SDK。

```kotlin
// 开启视频模块
mRtcEngine.enableVideo()
// 注册原始视频数据观测器
// 自定义视频采集时，即 CaptureMode 为 Custom 时，你需要注册原始视频观测器
mRtcEngine.registerVideoFrameObserver(object : IVideoFrameObserver {

    override fun onCaptureVideoFrame(
        sourceType: Int,
        videoFrame: VideoFrame?
    ) = when (mFaceUnityApi.onFrame(videoFrame!!)) {
        // 当处理结果为 SKIPPED（忽略）时，代表你丢帧，即外部自采集的视频数据不传入声网 RTC SDK
        // 当处理结果为其他时，外部自采集的视频数据传入声网 RTC SDK
        ErrorCode.ERROR_FRAME_SKIPPED.value -> false
        else -> true
    }

    // 设置是否对原始视频数据作镜像处理
    override fun getMirrorApplied() = mFaceUnityApi.getMirrorApplied()

    // 设置观测点为本地采集时的视频数据
    override fun getObservedFramePosition() = IVideoFrameObserver.POSITION_POST_CAPTURER

    // override 视频观测器中的其他回调函数
    ...
})
```

### 6. 加入频道 [#6-加入频道]

调用 `RtcEngine` 类的 `joinChannel` 加入频道，同时传入如下参数：

- `token`：用于鉴权的动态密钥。如果在[创建声网项目](/zh-CN/solutions/showroom/build/enable-service#创建声网项目)时启用**调试模式**，那么将 `token` 参数传空。如果启用**安全模式**，那么你先参考[使用 Token 鉴权](/zh-CN/realtime-media/rtc/build/setup-and-access/token-authentication)在你的业务服务端生成 Token，然后将生成的 Token 传入该参数。
- `channelId`：频道名。
- `options`：频道媒体设置选项。

```kotlin
mRtcEngine.joinChannel(null, mChannelName, 0, ChannelMediaOptions().apply {
    // 设置频道场景为直播
    channelProfile = Constants.CHANNEL_PROFILE_LIVE_BROADCASTING
    // 设置用户角色为主播，主播可以在频道里发布和订阅音视频流
    clientRoleType = Constants.CLIENT_ROLE_BROADCASTER
    // 设置是否发布摄像头采集的视频流（适用于使用声网模块采集视频的情况）
    publishCameraTrack = true
    // 设置是否发布自定义采集的视频流（适用于自定义采集视频的情况）
    publishCustomVideoTrack = false
    // 设置是否发布麦克风采集的音频流
    publishMicrophoneTrack = false
    // 设置进入频道时是否自动订阅频道内其他用户的音频流
    autoSubscribeAudio = false
    // 设置进入频道时是否自动订阅频道内其他用户的视频流
    autoSubscribeVideo = true
})
```

### 7.（可选）更新摄像头配置 [#7可选更新摄像头配置]

Beauty API 默认的镜像行为如下：

- 使用设备前置摄像头时，本地和远端视图都使用镜像。
- 使用设备后置摄像头时，本地和远端视图都不使用镜像。

如果默认的摄像头配置不满足你的业务需求，你可以参考本节更新摄像头配置。具体步骤如下：

调用 Beauty API 的 `updateCameraConfig` 并通过 `cameraConfig` 配置前置和后置摄像头的镜像效果。所有镜像类型包含如下：

- `MIRROR_LOCAL_REMOTE`：本地和远端视图都使用镜像。前置摄像头默认使用该配置。
- `MIRROR_LOCAL_ONLY`：本地视图使用镜像，远端视图不使用镜像。建议在直播画面中会出现告示牌或者文字的情况下使用该配置。
- `MIRROR_REMOTE_ONLY`：本地视图不使用镜像，远端视图使用镜像。
- `MIRROR_NONE`：本地和远端视图都不使用镜像。后置摄像头默认使用该配置。

```kotlin
val isFront = mFaceUnityApi.isFrontCamera()
// 判断 isFrontCamera
if (isFront) {
    cameraConfig = CameraConfig(
        // 通过 frontMirror 配置前置摄像头
        frontMirror = when (cameraConfig.frontMirror) {
            MirrorMode.MIRROR_LOCAL_REMOTE -> MirrorMode.MIRROR_LOCAL_ONLY
            MirrorMode.MIRROR_LOCAL_ONLY -> MirrorMode.MIRROR_REMOTE_ONLY
            MirrorMode.MIRROR_REMOTE_ONLY -> MirrorMode.MIRROR_NONE
            MirrorMode.MIRROR_NONE -> MirrorMode.MIRROR_LOCAL_REMOTE
        },
        backMirror = cameraConfig.backMirror
    )
} else {
    cameraConfig = CameraConfig(
        frontMirror = cameraConfig.frontMirror,
        // 通过 backMirror 配置后置摄像头
        backMirror = when (cameraConfig.backMirror) {
            MirrorMode.MIRROR_NONE -> MirrorMode.MIRROR_LOCAL_REMOTE
            MirrorMode.MIRROR_LOCAL_REMOTE -> MirrorMode.MIRROR_LOCAL_ONLY
            MirrorMode.MIRROR_LOCAL_ONLY -> MirrorMode.MIRROR_REMOTE_ONLY
            MirrorMode.MIRROR_REMOTE_ONLY -> MirrorMode.MIRROR_NONE
        }
    )
}
// 更新摄像头配置
mFaceUnityApi.updateCameraConfig(cameraConfig)
```

### 8. 离开频道 [#8-离开频道]

调用 `RtcEngine` 类的 `leaveChannel` 离开频道。

```kotlin
mRtcEngine.leaveChannel()
```

### 9. 销毁资源 [#9-销毁资源]

调用 Beauty API 的 `release` 销毁 Beauty API。

```kotlin
mFaceUnityApi.release()
```

调用美颜 SDK 的 `destroy` 销毁 `FURenderKit`。

```kotlin
FURenderKit.destroy()
```

调用 `RtcEngine` 的 `destroy` 销毁 `RtcEngine`。

```kotlin
RtcEngine.destroy()
```

### API 时序图 [#api-时序图]

![](https://web-cdn.agora.io/docs-portal/img/showroom/fu-and.svg)
<_PlatformProcessedMarker close="true" />

<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="android" platform="ios" />
本文介绍如何通过声网美颜场景化 API (Beauty API) 集成相芯美颜到实时音视频互动中。
## 示例项目 [#示例项目-1]

声网在 GitHub 上提供开源 `BeautyAPI` 示例项目供你参考。

<Cards>
  <Card title="BeautyAPI" href="https://github.com/AgoraIO-Community/BeautyAPI" />
</Cards>

## 准备开发环境 [#准备开发环境-1]

### 前提条件 [#前提条件-1]

开始前，请确保满足以下前提条件：

- [Git](https://git-scm.com/downloads)
- [CocoaPods](https://guides.cocoapods.org/using/getting-started.html#getting-started)
- [Xcode](https://apps.apple.com/cn/app/xcode/id497799835?mt=12) 12.0 及以上
- iOS 设备，版本 13.0 及以上
- 有效的苹果开发者账号
- [开通秀场直播服务](/zh-CN/solutions/showroom/build/enable-service)
- 已联系相芯技术获取最新的美颜 SDK、美颜资源、美颜证书

### 创建项目并集成 SDK [#创建项目并集成-sdk-1]

在 Xcode 中进行以下操作，在你的 App 中实现场景化美颜功能：

1. [创建一个新的项目](https://help.apple.com/xcode/mac/current/#/dev07db0e578)，**Application** 选择 **App**，**Interface** 选择 **Storyboard**，**Language** 选择 **Swift**。

    :::warning[注意]
    如果你没有添加过开发团队信息，会看到 **Add account…** 按钮。点击该按钮并按照屏幕提示登入 Apple ID，点击 **Next**，完成后即可选择你的 Apple 账户作为开发团队。
    :::

2. 为你的项目设置[自动签名](https://help.apple.com/xcode/mac/current/#/dev23aab79b4)。

3. 设置部署你的 App 的[目标设备](https://help.apple.com/xcode/mac/current/#/deve69552ee5)。

4. 添加项目的设备权限。在项目导航栏中打开 `info.plist` 文件，编辑[属性列表](https://help.apple.com/xcode/mac/current/#/dev3f399a2a6)，添加以下属性：

    | key                                    | type   | value                                                        |
    | -------------------------------------- | ------ | ------------------------------------------------------------ |
    | Privacy - Microphone Usage Description | String | 使用麦克风的目的，例如 for a live interactive streaming |
    | Privacy - Camera Usage Description       | String | 使用摄像头的目的，例如 for a live interactive streaming |

    :::warning[注意]
    - 如果你的项目中需要添加第三方插件或库（例如第三方摄像头），且该插件或库的签名与项目的签名不一致，你还需勾选 **Hardened Runtime > Runtime Exceptions** 中的 **Disable Library Validation**。
    - 更多注意事项，可以参考 [Preparing Your App for Distribution](https://developer.apple.com/documentation/xcode/preparing_your_app_for_distribution)。
    :::

5. 将相芯美颜 SDK 复制到你的项目中：请联系相芯技术支持获取美颜 SDK、美颜资源、证书等文件。下载并解压文件，然后添加到美颜项目对应的文件路径下：

    | 文件 | 项目路径 |
    | --- | --- |
    | `https://github.com/Faceunity/FULiveDemo/tree/master/FURenderKit/Resources/model` | `iOS/FULib/Resources/model/*.bundle` |
    | `https://github.com/Faceunity/FULiveDemo/tree/master/FURenderKit/Resources/graphics` | `iOS/FULib/Resources/graphics/*.bundle` |
    | 美妆资源：例如 `naicha.bundle` | `iOS/FULib/Resources/美妆/*.bundle` |
    | 贴纸资源：例如 `fashi.bundle` | `iOS/FULib/Resources/贴纸/*.bundle` |
    | 证书：`authpack.h` | `iOS/BeautyAPi/FUBeauty/authpack.h` |

6. 将声网美颜场景化 API 集成到你的项目中。添加 [iOS/BeautyAPI/BeautyAPI](https://github.com/AgoraIO-Community/BeautyAPI/tree/main/iOS/BeautyAPI/BeautyAPI) 目录下的文件到项目中，具体文件如下：

    - `Render/FURender` 文件夹
    - `BeautyAPI.h` 文件
    - `BeautyAPI.m` 文件

    :::warning[注意]
    为方便后续代码升级，请不要修改你添加的这些文件的名称和路径。
    :::

7. 将声网 RTC SDK 和相芯美颜依赖库集成到你的项目。

    1. 在终端里进入项目根目录，并运行 `pod init` 命令。项目文件夹下会生成一个 `Podfile` 文本文件。
    2. 打开 `Podfile` 文件，修改文件为如下内容。注意将 `Your App` 替换为你的 Target 名称。

    ```ruby
    platform :ios, '9.0'
    # 替换成你的 target 名称
    target 'Your App' do
        # x.y.z 请填写具体的 RTC SDK 版本号，如 4.0.1 或 4.0.0.4
        # 可通过实时互动发版说明获取最新版本号
        pod 'AgoraRtcEngine_iOS', 'x.y.z'
        # 配置相芯美颜的依赖库
        pod 'fuLib', :path => 'fu.podspec'
    end
    ```

8. 在终端内运行 `pod install` 命令安装声网 RTC SDK 和相芯美颜依赖。

9. 成功安装后，Terminal 中会显示 `Pod installation complete!`。项目文件夹下会生成一个后缀为 `.xcworkspace` 的文件，通过 Xcode 打开该文件进行后续操作。

## 实现美颜 [#实现美颜-1]

本节展示如何在直播间内实现美颜功能，参考 [API 时序图](#api-时序图-1)可查看总览。声网 RTC SDK 承担实时音视频的业务，相芯美颜 SDK 提供美颜功能，声网 Beauty API 封装了两个 SDK 中的 API 调用逻辑以简化你需要实现的代码逻辑。通过 Beauty API，你可以实现基础美颜功能，但是如果你还需要更丰富的美颜效果，例如贴纸、美妆风格，请直接调用美颜 SDK 中的 API。

### 1. 初始化 AgoraRtcEngineKit [#1-初始化-agorartcenginekit]

调用声网 RTC SDK 中的 `sharedEngineWithConfig` 创建并初始化 `AgoraRtcEngineKit` 对象。调用 `enableVideo` 开启声网 RTC SDK 的视频模块。

```swift
// 初始化 AgoraRtcEngineKit
private lazy var rtcEngine: AgoraRtcEngineKit = {
    let config = AgoraRtcEngineConfig()
    // 传入你从控制台获取的声网项目的 APP ID
    config.appId = KeyCenter.AppId
    config.channelProfile = .liveBroadcasting
    let rtc = AgoraRtcEngineKit.sharedEngine(with: config, delegate: self)
    // 设置用户角色为主播，主播可以发送音视频流也可以接收音视频流
    rtc.setClientRole(.broadcaster)
    // 开启 SDK 音频模块
    rtc.enableAudio()
    // 开启 SDK 视频模块
    rtc.enableVideo()
    // 设置默认音频路由为扬声器
    rtc.setDefaultAudioRouteToSpeakerphone(true)
    return rtc
}()
```

### 2. 初始化美颜和 Beauty API [#2-初始化美颜和-beauty-api]

创建 `FUBeautyRender` 和 Beauty API 对象。Beauty API 对象基于 `FUBeautyRender` 对象封装。

```swift
private lazy var fuRender = FUBeautyRender()
private lazy var beautyAPI = BeautyAPI()
```

调用 `initialize` 初始化 Beauty API 对象。你需要在 `config` 参数中传入如下字段：

- `AgoraRtcEngineKit`：传入之前初始化的 `AgoraRtcEngineKit` 对象。
- `beautyRender`：传入之前初始化的 `FUBeautyRender` 对象。
- `captureMode`：视频的采集模式：
    - 如果你使用声网模块采集视频，请传入 `CaptureMode.Agora`。
    - 如果自定义采集视频，请传入 `CaptureMode.Custom`。
- `cameraConfig`：设置视频镜像模式。如果在初始化 Beauty API 后你想修改镜像模式，可以调用 Beauty API 的 `updateCameraConfig`。
- `statsEnable`：是否开启美颜统计数据回调。`true` 代表开启，`false` 代表不开启。开启后，会有周期性回调事件。
- `statsDuration`：美颜统计数据回调的周期。单位为秒。
- `eventCallback`：监听的美颜统计数据回调事件。

```swift
let config = BeautyConfig()
// AgoraRtcEngineKit
config.rtcEngine = rtcEngine
// 设置视频采集模式
// .agora 意味着使用声网模块采集视频
// .custom 意味着使用开发者自定义采集视频
config.captureMode = capture == "Custom" ? .custom : .agora
// 配置视频镜像模式
config.cameraConfig = cameraConfig
// FUBeautyRender
config.beautyRender = fuRender
// 是否开启美颜统计数据
// 开启后，会有周期性回调事件
config.statsEnable = false
// 设置美颜统计数据的统计区间为 1 秒（默认）
config.statsDuration = 1
// Beauty API 的回调事件
config.eventCallback = { stats in
    print("min == \(stats.minCostMs)")
    print("max == \(stats.maxCostMs)")
    print("averageCostMs == \(stats.averageCostMs)")
}

// 初始化 Beauty API 对象
let result = beautyAPI.initialize(config)
if result != 0 {
    print("initialize error == \(result)")
}
```

### 3. 开启美颜 [#3-开启美颜]

调用 Beauty API 的 `enable` 方法并将参数设为 `true` 开启美颜。

```swift
beautyAPI.enable(true)
```

### 4. 开启视频采集 [#4-开启视频采集]

开发者可以使用声网模块采集视频，也可以自定义采集视频。本节介绍在这两种场景下如何开启视频采集。

#### 使用声网模块采集视频 [#使用声网模块采集视频-1]

使用声网模块采集视频时，调用 Beauty API 的 `setupLocalVideo` 开启本地视图。

```swift
beautyAPI.setupLocalVideo(localView, renderMode: .hidden)
```

#### 自定义视频采集 [#自定义视频采集-1]

使用自定义视频采集时，你需要在完成视频自采集后，通过 Beauty API 的 `onFrame` 函数将外部自采集的视频数据传入并进行处理。

如下示例代码展示通过声网 RTC SDK 的 API 进行的自定义视频采集，具体逻辑为通过 `AgoraRtcEngineKit` 类的 `setVideoFrameDelegate` 注册原始视频数据观测器并在其中实现 `onCaptureVideoFrame` 函数。你可以根据实际情况参考这种自采集方式，或使用第三方视频自采集。

```swift
if capture == "Custom" {
    // 注册原始视频数据观测器
    // 自定义视频采集时，即 CaptureMode 为 Custom 时，你需要注册原始视频观测器
    rtcEngine.setVideoFrameDelegate(self)
}

extension BeautyViewController: AgoraVideoFrameDelegate {
    func onCapture(_ videoFrame: AgoraOutputVideoFrame, sourceType: AgoraVideoSourceType) -> Bool {
        // 将外部自采集的视频数据传入声网 RTC SDK
        guard let pixelBuffer = videoFrame.pixelBuffer else { return true }
        beautyAPI.onFrame(pixelBuffer) { pixelBuffer in
            videoFrame.pixelBuffer = pixelBuffer
        }

        return true
    }

    // 设置是否对原始视频数据作镜像处理
    func getMirrorApplied() -> Bool {
        beautyAPI.getMirrorApplied()
    }

    // 设置观测点为本地采集时的视频数据
    func getObservedFramePosition() -> AgoraVideoFramePosition {
        .postCapture
    }

    // 实现视频观测器中的其他回调函数
    ...
}
```

### 5. 加入频道 [#5-加入频道]

调用 `AgoraRtcEngineKit` 类的 `joinChannelByToken` 加入频道，同时传入如下参数：

- `token`：用于鉴权的动态密钥。如果在[创建声网项目](/zh-CN/solutions/showroom/build/enable-service#创建声网项目)时启用**调试模式**，那么将 `token` 参数传空。如果启用**安全模式**，那么你先参考[使用 Token 鉴权](/zh-CN/realtime-media/rtc/build/setup-and-access/token-authentication)在你的业务服务端生成 Token，然后将生成的 Token 传入该参数。
- `channelId`：频道名。
- `mediaOptions`：频道媒体设置选项。

```swift
let mediaOption = AgoraRtcChannelMediaOptions()
mediaOption.clientRoleType = isBroadcast ? .broadcaster : .audience
// 设置进入频道时是否自动订阅频道内其他用户的音频流
mediaOption.autoSubscribeAudio = true
// 设置进入频道时是否自动订阅频道内其他用户的视频流
mediaOption.autoSubscribeVideo = true
// 设置是否发布摄像头采集的视频流（适用于使用声网模块采集视频的情况）
// 用户角色为主播时，设置发布
// 用户角色为观众时，设置不发布
mediaOption.publishCameraTrack = mediaOption.clientRoleType == .broadcaster
// 设置是否发布自定义采集的视频流（适用于自定义采集视频的情况）
mediaOption.publishCustomVideoTrack = false
// 设置是否发布麦克风采集的音频流
// 用户角色为主播时，设置发布
// 用户角色为观众时，设置不发布
mediaOption.publishMicrophoneTrack = mediaOption.clientRoleType == .broadcaster

// 加入频道
let result = rtcEngine.joinChannel(byToken: nil, channelId: channelName ?? "", uid: 0, mediaOptions: mediaOption)
if result != 0 {
    print("join failed")
}
```

### 6.（可选）更新摄像头配置 [#6可选更新摄像头配置]

Beauty API 默认使用设备前置摄像头参与直播。默认的镜像行为如下：

- 使用设备前置摄像头时，本地和远端视图都使用镜像。
- 使用设备后置摄像头时，本地和远端视图都不使用镜像。

如果默认的摄像头配置不满足你的业务需求，你可以参考本节更新摄像头配置。具体步骤如下：

1. 如果当前使用的摄像头不是前置，那么调用 Beauty API 的 `switchCamera` 切换摄像头。调用后，Beauty API 内部会通过 `isFrontCamera` 知晓当前使用的是前置还是后置摄像头，从而在后续步骤中让你能针对前后置摄像头设置正确的镜像效果。

    ```swift
    beautyAPI.switchCamera()
    ```

    多次调用该方法可以多次切换前后置摄像头。

2. 如果默认的镜像行为不满足你的业务需求，那么调用 Beauty API 的 `updateCameraConfig` 并通过 `cameraConfig` 配置前置和后置摄像头的镜像效果。所有镜像类型包含如下：

    - `LOCAL_REMOTE`：本地和远端视图都使用镜像。前置摄像头默认使用该配置。
    - `LOCAL_ONLY`：本地视图使用镜像，远端视图不使用镜像。建议在直播画面中会出现告示牌或者文字的情况下使用该配置。
    - `REMOTE_ONLY`：本地视图不使用镜像，远端视图使用镜像。
    - `NONE`：本地和远端视图都不使用镜像。后置摄像头默认使用该配置。

    ```swift
    let cameraConfig = BeautyManager.shareManager.cameraConfig
    // 判断 isFrontCamera
    if self.beautyAPI?.isFrontCamera ?? false {
        // 通过 frontMirror 配置前置摄像头
        cameraConfig.frontMirror = Configs.mirrorTypes[value] ?? .LOCAL_REMOTE
    } else {
        // 通过 backMirror 配置后置摄像头
        cameraConfig.backMirror = Configs.mirrorTypes[value] ?? .NONE
    }
    // 更新摄像头配置
    self.beautyAPI?.update(cameraConfig)
    ```

### 7. 离开频道 [#7-离开频道]

调用 `AgoraRtcEngineKit` 类的 `leaveChannel` 离开频道。

```swift
rtcEngine.leaveChannel()
```

### 8. 销毁资源 [#8-销毁资源]

调用 Beauty API 的 `destroy` 销毁 Beauty API。

```swift
beautyAPI.destroy()
```

:::warning[注意]
Beauty API 自 1.0.2 版起，已将存在笔误的 `destory` 方法名修正为 `destroy`。
:::

调用 `AgoraRtcEngineKit` 的 `destroy` 销毁 `AgoraRtcEngineKit`。

```swift
AgoraRtcEngineKit.destroy()
```

### API 时序图 [#api-时序图-1]

![](https://web-cdn.agora.io/docs-portal/img/showroom/fu-ios.svg)
<_PlatformProcessedMarker close="true" />
</_PlatformTabsGroup>
