使用 MetaKit 插件
本文介绍如何在你的项目中集成 MetaKit 插件,体验虚拟人、Animoji、Sticker、灯光特效和背景特效功能模块。
前提条件
在集成 MetaKit 插件前,请确保开发环境满足以下要求:
- 已集成 4.3.x 版本的实时互动 SDK,并确保你已在 App 中实现了基本的实时音视频功能,请参考实现音视频互动。
注意
- 通过 CocoaPods 集成时,打开
Podfile
,指定pod 'AgoraRtcEngine_Special_iOS', 'x.y.z'
,x.y.z
替换为具体的 SDK 版本号。 - MetaKit 插件需要用到实时互动 SDK 的面部捕捉插件 (
AgoraFaceCaptureExtension.xcframework
) 和虚拟背景插件 (AgoraVideoSegmentationExtension.xcframework
),你可以按需删除不需要的插件以减小 App 体积。
- 通过 CocoaPods 集成时,打开
- Xcode 13.0 及以上版本。
- iOS 14.0 及以上版本的真机设备,设备的前置摄像头与麦克风功能正常。
- Apple 开发者账号。
- 已安装 CocoaPods,详见 Getting Started with CocoaPods。
- 可以访问互联网的计算机。如果你的网络环境部署了防火墙,参考应对防火墙限制以正常使用声网服务。
集成 MetaKit 插件
在体验 MetaKit 插件前,请参考以下步骤配置你的项目。
添加 MetaKit 插件依赖
请参考以下步骤获取并集成 MetaKit 插件:
-
进入下载页面,下载并解压 MetaKit iOS 插件。
-
打开文件夹,解压
Libraries.zip
,将解压后的文件复制到对应的项目路径中。库 集成路径 AgoraMetaKitExtension.xcframework
/SDKExtension/
AgoraMetaKit.xcframework
/SDKExtension/
注意声网提供 XCFramework 格式的插件支持
arm64
架构,但不支持armv7
架构。 -
用 Xcode 打开项目,添加对应动态库的依赖,确保添加的动态库 Embed 属性设置为 Embed & Sign。
配置 MetaKit 资源
-
打开 MetaKit iOS 插件的文件夹,
/assets/
路径下包含不同场景及功能所需的 Bundle 文件资源。功能模块、用途说明和资源大小见下表:功能模块 用途说明 资源大小 虚拟人 虚拟人模型分包资源 ( material_avatar_xxx
),包含虚拟人形像girl
、boy
和huamulan
。可使用面捕驱动、捏脸、换装等能力。material_avatar_girl
: 17.7 MBmaterial_avatar_boy
: 5.4 MB(不支持换装)material_avatar_huamulan
: 5.3 MB(不支持捏脸换装)
Animoji Animoji 模型分包资源 ( material_animoji_xxx
),包含 Animoji 形象dog
、girlhead
和arkit
。可使用面捕驱动能力。material_animoji_dog
: 3.3 MBmaterial_animoji_girlhead
: 4.2 MBmaterial_animoji_arkit
: 2 MB
Sticker Sticker 模型分包资源 ( material_sticker_xxx
),包含 Sticker 挂件glass
、facemask
、dragonhat
和veil
。可使用面捕驱动能力。material_sticker_glass
: 2.5 MBmaterial_sticker_facemask
: 1.9 MBmaterial_sticker_dragonhat
: 2.4 MBmaterial_sticker_veil
: 2.6 MB
背景特效 背景特效分包资源 ( material_bgeffect_xxx
),包含360
(360 全景背景)和3d
(3D 背景)。material_bgeffect_360
: 3.1 MBmaterial_bgeffect_3d
: 5.6 MB
灯光特效 灯光特效分包资源 ( material_effect_xxx
),包含 3D 打光、广告灯、氛围灯、极光特效、人像边缘火焰、人像边缘光线和屏幕波纹。material_effect_3dlight
: 1.9 MBmaterial_effect_advertiselight
: 8.2 MBmaterial_effect_envlight
: 1.9 MBmaterial_effect_aura
: 2 MBmaterial_effect_purpleflame
: 2 MBmaterial_effect_ray
: 1.9 MBmaterial_effect_wave
: 1.9 MB
-
每个单包资源 (
material_xxx
) 代表一种场景效果。将多个你想体验的单包资源资源 (material_xxx
) 平行放置在一个根目录下,加载场景资源时,将资源目录的绝对路径设置给 MetaKit。例如,体验女孩虚拟形象和人像边缘火焰特效,步骤如下:- 将
material_avatar_girl
和material_effect_purpleflame
合成一个资源目录(如下图所示)。准备好资源目录后,将其放置在移动设备 SD 卡的目录下,如/sdcard/metaAssets/
。 loadMaterial
时,将路径设置为/sdcard/metaAssets/material_avatar_girl
,体验女孩虚拟人场景。- 再次
loadMaterial
,将路径指定为/sdcard/metaAssets/material_effect_purpleflame
,切换为人像边缘火焰。
注意业务层需自行确保下载解压后资源的完备性。如果目录不正确或有 Bundle 文件丢失的情况,加载时会出现异常。
- 将
添加 iOS 设备权限
打开项目的 Info.plist
文件,编辑属性列表,添加体验 MetaKit 插件所需的麦克风和摄像头权限。
权限 | 说明 |
---|---|
Privacy - Microphone Usage Description | 使用音频功能。 |
Privacy - Camera Usage Description | 表情驱动、背景分割等功能需要访问摄像头以做 AI 推理。 |
体验 MetaKit 插件
项目配置完成后,请参照以下步骤体验 MetaKit 插件的各个功能模块。
监听插件事件回调
-
调用
sharedEngineWithConfig
初始化AgoraRtcEngineKit
时,你需要在AgoraRtcEngineConfig
中创建插件的事件回调接口类AgoraMediaFilterEventDelegate
,并注册onEvent
等插件事件回调。Swiftlet config = AgoraRtcEngineConfig()
config.appId = appID
config.eventDelegate = self
// 创建并初始化 AgoraRtcEngineKit
agoraEngine = AgoraRtcEngineKit.sharedEngine(with: config, delegate: self)
// 创建插件的事件回调接口类,注册 onEvent 等插件事件回调
extension ViewController: AgoraMediaFilterEventDelegate {
func onEvent(_ provider: String?, extension: String?, key: String?, value: String?) {
}
func onExtensionStarted(_ provider: String?, extension: String?) {
}
func onExtensionStopped(_ provider: String?, extension: String?) {
}
func onExtensionError(_ provider: String?, extension: String?, error: Int32, message: String?) {
}
} -
在回调中指定
provider
为agora_video_filters_metakit
,extension
为metakit
,即筛选来自 MetaKit 插件的事件。onEvent
会透传引擎状态,如unityLoadFinish
(Unity 环境加载完成)和materialLoaded
(场景视图加载完成)等。注意- 下列代码注释中介绍了每个引擎状态的含义及时序,请确保在收到确切的引擎状态后,执行对应的操作,以免出现不必要的时序问题。
- 引擎状态的回调不在主线程执行。如果需要在收到回调后执行其他重要操作,请使用
dispatch_async
将这些任务切换到主线程,以避免线程问题。
Swiftfunc onEvent(_ provider: String?, extension: String?, key: String?, value: String?) {
guard let provider = provider, let extension = extension, provider == "agora_video_filters_metakit", extension == "metakit" else {
return
}
guard let status = key else {
return
}
switch status {
case "initializeFinish":
// 引擎初始化完成
// 如有 initialize 操作,请在最后调用 destroy 销毁引擎,确保引擎的正常生命周期,减少对性能和内存的影响
break;
case "unityLoadFinish":
// Unity 环境加载完成
// 收到此状态后,可以调用 loadMaterial 加载场景资源
break;
case "materialLoaded":
// 加载场景资源成功
// 收到此状态后,可以根据场景进一步执行捏脸换装、特效参数设置等操作
// 如不再需要体验场景,调用 unloadMaterial 卸载场景资源
DispatchQueue.main.async {
// 回调不是主线程抛过来的,请在 dispatch 后执行操作
}
break;
case "materialUnLoaded":
// 卸载场景资源完成
// 收到此状态后,不可再次加载场景资源,仅可调用 destroy 执行引擎销毁操作
break;
default:
break
}
}
func onExtensionError(_ provider: String?, extension: String?, error: Int32, message: String?) {
if provider == "agora_video_filters_metakit" && extension == "metakit" {
print("[MetaKit] onExtensionError, Code: \(error), Message: \(message ?? "")")
}
}
启用插件
启用面部捕捉插件、虚拟背景插件和 MetaKit 插件。
在启用 MetaKit 插件前,你需要先启用面部捕捉插件和虚拟背景插件。
-
启用面部捕捉插件。
- 调用
registerExtensionWithVendor
和enableExtensionWithVendor
注册并启用面部捕捉插件,传入对应的插件服务商名称 (agora_video_filters_face_capture
) 和插件名称 (face_capture
)。 - 调用
setExtensionPropertyWithVendor
认证和授权面部捕捉插件的 AI 模块,其中key
为authentication_information
,value
包含公司名称 (company_id
) 和面捕证书 (license
)。
注意公司名称和面捕证书需要联系 sales@shengwang.cn 获取。
Swift// 注册面部捕捉插件
agoraEngine?.registerExtension(withVendor: "agora_video_filters_face_capture", extension: "face_capture", sourceType: AgoraMediaSourceType.primaryCamera)
// 启用面部捕捉插件
agoraEngine?.enableExtension(withVendor: "agora_video_filters_face_capture", extension: "face_capture", enabled: true)
// 授权面部捕捉插件
agoraEngine?.setExtensionPropertyWithVendor("agora_video_filters_face_capture",
extension: "face_capture",
key: "authentication_information",
value: "{\"company_id\":\"agoraDemo\", \"license\":\"xxxxxxxxxx"}",
sourceType: AgoraMediaSourceType.primaryCamera) - 调用
-
启用虚拟背景插件。
- 调用
setParameters
设置"rtc.video.seg_before_exts"
为true
,确保虚拟背景插件优先于 MetaKit 插件执行。 - 调用
enableVirtualBackground
开启虚拟背景,其中:- 指定背景填充 (
backgroundSourceType
) 为AgoraVirtualBackgroundNone
,将背景处理为 alpha 信息,即分割人像和背景。 - 指定分割模式 (
modelType
) 为SegModelAgoraAi
,即选择适用于全部场景的背景处理。
- 指定背景填充 (
Swift// 确保虚拟背景插件优先于 MetaKit 插件执行
agoraKit.setParameters("{\"rtc.video.seg_before_exts\":true}")
let bg_src = AgoraVirtualBackgroundSource()
// 将背景处理为 alpha 信息,分割人像和背景
bg_src.backgroundSourceType = .none
let seg_prop = AgoraSegmentationProperty()
seg_prop.greenCapacity = 0
// 选择适用于全部场景的背景处理
seg_prop.modelType = .agoraAi
// 启用虚拟背景插件
agoraEngine?.enableVirtualBackground(true, backData: bg_src, segData: seg_prop) - 调用
-
启用 MetaKit 插件。
调用registerExtensionWithVendor
和enableExtensionWithVendor
注册并启用 MetaKit 插件,传入对应的插件服务商名称 (agora_video_filters_metakit
) 和插件名称 (metakit
)。Swift// 注册 MetaKit 插件
agoraEngine?.registerExtension(withVendor: "agora_video_filters_metakit", extension: "metakit", sourceType: AgoraMediaSourceType.primaryCamera)
// 启用 MetaKit 插件
agoraEngine?.enableExtension(withVendor: "agora_video_filters_metakit", extension: "metakit", enabled: true)
初始化插件
调用 setExtensionPropertyWithVendor
初始化 MetaKit 插件,其中 key
为 initialize
,value
为空。
agoraEngine?.setExtensionPropertyWithVendor("agora_video_filters_metakit", extension: "metakit", key:"initialize", value:"{}")
创建渲染视图
当 onEvent
回调捕获到 unityLoadFinish
事件时,代表 Unity 环境已加载完成。此时,调用 createSceneView
创建一个 SceneView 用于显示 MetaKit 插件的渲染画面。
let metakit: MetaKitEngine = MetaKitEngine.sharedInstance()
var frame = CGRect(x: 0, y: 0, width: 360, height: 640);
// 1. sceneView 为原生 iOS UIView,如果需要展示在 UI 上,可自行添加到父 view 上
// 2. 如果想要铺满渲染画面,sceneView 的 frame 尽量确保和素材的比例是对等的(默认 9:16)
// 否则画面会按等比例适应,画面居中,上下左右留白
let sceneView = metakit.createSceneView(frame)
加载场景资源
创建好视图后,加载场景资源并渲染到该视图上。此时,可以调用 setExtensionPropertyWithVendor
加载 MetaKit 场景资源,其中 key
为 loadMaterial
,value
包含场景信息。
- 下文中虚拟人、Animoji、Sticker、灯光特效和背景特效的资源加载均类似此步骤 (
key
为loadMaterial
),区别仅在于加载的资源包不同 (value
中指定的资源包路径不同)。 - 资源加载操作 (
loadMaterial
) 可以多次执行,无需在每次加载后执行卸载操作 (unloadMaterial
) 。例如:在调用loadMaterial(pathA)
后,如需切换为其他场景资源,可以再次调用loadMaterial(pathB)
、loadMaterial(pathC)
等,每次加载会全量覆盖之前的场景,最后再执行unloadMaterial()
卸载场景资源即可。
let address = unsafeBitCast(avatarView!, to: Int64.self)
// path 为 Unity 的资源包目录,请提前下载并解压好
// view 为上文创建的 SceneView 的地址句柄
let dict = ["path": path, "view": String(address)]
let data = try? JSONSerialization.data(withJSONObject: dict, options: [])
let dictInfo = String(data: data!, encoding: String.Encoding.utf8)
self.agoraKit?.setExtensionPropertyWithVendor("agora_video_filters_metakit", extension: "metakit",
key:"loadMaterial",
value:dictInfo ?? "")
当 onEvent
回调捕获到 materialLoaded
事件时,代表场景资源已加载完成。接下来,你可以体验虚拟人、Animoji、Sticker、灯光特效和背景特效功能模块。
设置虚拟人
-
调用
setExtensionPropertyWithVendor
添加一个虚拟人场景,其中key
为loadMaterial
,value
为素材的配置信息。 你想选用哪个虚拟人形象,请指定对应的资源名 (material_avatar_xxx
),例如:女孩虚拟人形象的资源名为material_avatar_girl
。信息除
girl
、boy
和huamulan
三个插件中已有的虚拟形象外,声网 MetaKit 插件提供开放的美术生态,支持一键导入按声网的美术标准制作的虚拟人模型,为用户提供更灵活的创作和集成选项。联系声网技术支持使用该功能。Swiftlet address = unsafeBitCast(sceneView!, to: Int64.self) // 获取视图的地址句柄
let dict = ["path": path_to_material_avatar_girl, "view": String(address)]
let data = try? JSONSerialization.data(withJSONObject: dict, options: [])
let dictInfo = String(data: data!, encoding: String.Encoding.utf8)
self.agoraKit?.setExtensionPropertyWithVendor("agora_video_filters_metakit", extension: "metakit",
key:"loadMaterial",
value:dictInfo ?? "")当
onEvent
回调捕获到materialLoaded
事件时,代表场景视图已添加完成,视图中会展示一个 Blendshape 驱动的虚拟人形象,捕捉你的面部表情并作出对应的神态变化,跟随你的摆头等动作。 -
对虚拟人进行捏脸操作,支持以下两种方式:
- (推荐)方式一:加载虚拟人时,直接应用整套捏脸效果。只需要在
loadMaterial
时指定资源为material_package_faceshape
,即可加载虚拟人形象及整套捏脸数据。 - 方式二:加载虚拟人后,动态按部位对虚拟人进行捏脸操作。调用
setExtensionPropertyWithVendor
,其中key
为updateFace
,value
支持传入多组捏脸部位的资源 ID 及其对应的调节幅度。详见捏脸资源。
Swiftlet parts = [
// key 为捏脸部位的资源 ID
// value 为对应的捏脸幅度,取值范围为 [0,100],默认值为 50
["key": "C_updown_2", "value": 20],
["key": "EB_thickness", "value": 40],
["key": "E_width_1", "value": 60],
["key": "N_width_1", "value": 80]
]
let dict = ["value": parts]
let data = try? JSONSerialization.data(withJSONObject: dict, options: [])
let str = String(data: data!, encoding: String.Encoding.utf8)
// 根据 JSON 配置进行捏脸操作
agoraKit?.setExtensionPropertyWithVendor("agora_video_filters_metakit", extension: "metakit",
key:"updateFace",
value:str!) - (推荐)方式一:加载虚拟人时,直接应用整套捏脸效果。只需要在
-
对虚拟人进行换装操作,支持以下两种方式:
- (推荐)方式一:在加载虚拟人时,直接应用整套换装效果。在
loadMaterial
时指定资源为material_package_dress2
或material_package_dress3
,即可加载虚拟人形象及整套换装效果。 - 方式二:在加载虚拟人后,动态按部位对虚拟人进行换装操作。调用
setExtensionPropertyWithVendor
,其中key
为updateDress
,value
支持传入由多个换装部位的资源 ID 组成的 Int 数组。详见换装资源。
Swift// id 设置为多个资源 ID 组成的 Int 数组
let dict = ["id": [10002, 10102, 10402, 12102, 12501, 14102, 15002]]
let data = try? JSONSerialization.data(withJSONObject: dict, options: [])
let str = String(data: data!, encoding: String.Encoding.utf8)
// 根据 JSON 配置进行换装操作
agoraKit?.setExtensionPropertyWithVendor("agora_video_filters_metakit", extension: "metakit",
key:"updateDress",
value:str!)此外,MetaKit 插件还支持切换虚拟人的形象和视角,详见虚拟人 key-value 说明。
- (推荐)方式一:在加载虚拟人时,直接应用整套换装效果。在
设置 Animoji 和 Sticker
- Animoji
- Sticker
调用 setExtensionPropertyWithVendor
添加一个 Animoji 场景,其中 key
为 loadMaterial
,value
为素材的配置信息。你想选用哪个 Animoji 效果,请指定对应的资源名 (material_animoji_xxx
),例如:狗狗头套 Anomoji 的资源名为 material_animoji_dog
。
除 dog
、girlhead
和 arkit
三个插件中已有的 Animoji 外,声网 MetaKit 插件提供开放的美术生态,支持一键导入按声网的美术标准制作的 Animoji 形象,为用户提供更灵活的创作和集成选项。联系声网技术支持使用该功能。
let address = unsafeBitCast(sceneView!, to: Int64.self) // 获取视图的地址句柄
let dict = ["path": path_to_material_animoji_dog, "view": String(address)]
let data = try? JSONSerialization.data(withJSONObject: dict, options: [])
let dictInfo = String(data: data!, encoding: String.Encoding.utf8)
self.agoraKit?.setExtensionPropertyWithVendor("agora_video_filters_metakit", extension: "metakit",
key:"loadMaterial",
value:dictInfo ?? "")
当 onEvent
回调捕获到 materialLoaded
事件时,代表场景视图已添加完成。此时,画面中会出现一个遮住人脸的狗狗头套,捕捉你的面部表情并作出对应的神态变化,跟随你的摆头等动作。此外,MetaKit 插件支持你切换 Animoji 形象并调节 Animoji 形象的渲染等级,详见 Animoji key-value 说明。
调用 setExtensionPropertyWithVendor
添加一个 Sticker 场景视图,其中 key
为 loadMaterial
,value
为素材的配置信息。你想选用哪个 Sticker 效果,请指定对应的资源名 (material_sticker_xxx
),例如:眼镜贴纸的资源名为 material_sticker_glass
。
除 veil
、glass
、facemask
和 dragonhat
四个插件中已有的 Sticker 外,声网 MetaKit 插件提供开放的美术生态,支持一键导入按声网的美术标准制作的 Sticker 形象,为用户提供更灵活的创作和集成选项。联系声网技术支持使用该功能。
let address = unsafeBitCast(sceneView!, to: Int64.self) // 获取视图的地址句柄
let dict = ["path": path_to_material_sticker_glass, "view": String(address)]
let data = try? JSONSerialization.data(withJSONObject: dict, options: [])
let dictInfo = String(data: data!, encoding: String.Encoding.utf8)
self.agoraKit?.setExtensionPropertyWithVendor("agora_video_filters_metakit", extension: "metakit",
key:"loadMaterial",
value:dictInfo ?? "")
当 onEvent
回调捕获到 materialLoaded
事件时,代表场景视图已添加完成。此时,视图中会展示一个遮住人眼的眼镜贴纸,跟随你的摆头等动作。
设置灯光和背景特效
- 灯光特效
- 背景特效
-
调用
setExtensionPropertyWithVendor
添加一个灯光特效场景,其中key
为loadMaterial
,value
为素材的配置信息。你想选用哪个灯光特效,请指定对应的资源名 (material_effect_xxx
),例如:3D 打光的资源名为material_effect_3dlight
。成功设置该特效后,画面中会有一盏 3D 灯光从斜方来回扫过。Swiftlet address = unsafeBitCast(sceneView!, to: Int64.self) // 获取视图的地址句柄
let dict = ["path": path_to_material_effect_3dlight, "view": String(address)]
let data = try? JSONSerialization.data(withJSONObject: dict, options: [])
let dictInfo = String(data: data!, encoding: String.Encoding.utf8)
self.agoraKit?.setExtensionPropertyWithVendor("agora_video_filters_metakit", extension: "metakit",
key:"loadMaterial",
value:dictInfo ?? "") -
调用
setExtensionPropertyWithVendor
调节灯光特效的参数,其中key
为setEffectVideo
,value
中包含一系列灯光素材的配置参数。MetaKit 插件提供 3D 打光、屏幕波纹、极光特效、人像边缘火焰等灯光特效,并支持对灯光效果的颜色、强度、范围等参数进行精细化配置,详见灯光特效 key-value 说明。Swiftlet address = unsafeBitCast(sceneView!, to: Int64.self) // 获取视图的地址句柄
let light_dict = ["id": 1001, "param": ["intensity": 2.0, "scale": 0.3] as [String : Any], "enable": true] as [String : Any]
let light_data = try? JSONSerialization.data(withJSONObject: light_dict, options: [])
let light_info = String(data: light_data!, encoding: String.Encoding.utf8)
agoraKit?.setExtensionPropertyWithVendor("agora_video_filters_metakit", extension: "metakit",
key:"setEffectVideo",
value:light_info!)
调用 setExtensionPropertyWithVendor
添加一个背景特效场景,其中 key
为 loadMaterial
,value
为素材的配置信息。你想选用哪个背景特效,请指定对应的资源名 (material_bgeffect_xxx
),例如:360 全景背景素材的资源名为 material_bgeffect_360
。
let address = unsafeBitCast(sceneView!, to: Int64.self) // 获取视图的地址句柄
let dict = ["path": path_to_bgeffect, "view": String(address)]
let data = try? JSONSerialization.data(withJSONObject: dict, options: [])
let dictInfo = String(data: data!, encoding: String.Encoding.utf8)
self.agoraKit?.setExtensionPropertyWithVendor("agora_video_filters_metakit", extension: "metakit",
key:"loadMaterial",
value:dictInfo ?? "")
成功设置该特效后,可以观察到视频画面背景变为 360 全景,转动手机能体验到全景效果。此外,MetaKit 插件还支持 2D 背景和 3D 背景,如需将背景替换为指定资源或开启陀螺仪效果,详见背景特效 key-value 说明。
开启视图输出
调用 setExtensionPropertyWithVendor
开启视图输出,其中 key
为 enableSceneVideo
,value
中将 enable
设置为 true
开启场景视图的画面捕获。开启视图输出后,本地视图的渲染效果会传输到远端,加入频道的观众也能看到渲染效果。
let address = unsafeBitCast(sceneView!, to: Int64.self)
let value = enable ? 1 : 0
agoraKit?.setExtensionPropertyWithVendor("agora_video_filters_metakit",
extension: extension_name,
key:"enableSceneVideo",
value:"{\"view\":\"\(address)\",\"enable\":\(value)}")
释放资源
停止使用插件时,可以参照以下示例代码卸载场景资源、移除场景视图并销毁引擎。
// 1. 卸载场景资源
agoraEngine?.setExtensionPropertyWithVendor("agora_video_filters_metakit", extension: "metakit",
key:"unloadMaterial", value:"{}")
// 2. 移除视图
sceneView?.removeFromSuperview()
metakit.removeSceneView(sceneView?)
// 3. 收到 materialUnLoaded 后,执行销毁引擎
agoraEngine?.setExtensionPropertyWithVendor("agora_video_filters_metakit", extension: "metakit",
key:"destroy", value:"{}")