• 元宇宙场景技术实践|实现“虚拟人”自由


    虚拟形象是虚拟世界的核心资产,也是打造元宇宙社交的数字名片,从虚拟形象为切入点,ZEGO Avatar 基于强大的 AI 算法能力,可以为企业提供多元化风格虚拟形象制作及智能互动服务,助力企业打造虚拟形象数字资产,创造多样的玩法体验,支持客户以相对较低的门槛快速进入元宇宙赛道。

    上期内容中我们介绍了元宇宙场景下的虚拟直播实践流程,本期内容我们以 iOS 版本为例来讲一讲如何捏出千人千面的虚拟形象,助力开发者快速实现虚拟形象!

    前提条件

    在实现基本的 Avatar 功能之前,请确保:

    • 已在项目中集成了 Avatar SDK,详情请参考 集成 SDK

    • 已开启摄像头权限。

    =======

    使用步骤

    =================

    本节介绍如何使用 ZegoAvatar SDK 实现基本的图像处理功能,API 调用时序如下图:


    1申请鉴权

    ZEGO Avatar 目前使用 在线鉴权 的方式获取 License 授权文件。

    1.1 开通 ZegoAvatar 权限

    • 请先在 ZEGO 控制台 创建项目,并申请有效的 AppID 和 AppSign,详情请参考 控制台 - 项目管理 中的“项目信息”。

    • 请联系 ZEGO 商务人员,提供自己项目的 Bundle Id,开通相关权限。

    1.2 获取参考代码

    请将从 下载 获取到的示例源码中的 LicenseHelper 文件夹中的代码,拷贝到自己的项目下。

    • 修改 ZegoAvatarConfig.h 文件,请使用已获取的 AppID 和 AppSign 正确填写,否则示例源码无法正常运行。
    
    // 鉴权服务器的地址
    static NSString *AVATAR_BASE_URL = @"https://aieffects-api.zego.im?Action=DescribeAvatarLicense";
    
    // 向 ZEGO 申请的 AppID, APPID 跟 Bundle Id 有绑定关系,“Bundle Identifier” 设置为申请 AppID 时所提供的 Bundle Id
    static NSUInteger AVATAR_APPID = YOUR_APP_ID;
    
    // 向 ZEGO 申请的得到的 AppSign
    static NSString *AVATAR_APP_SIGN = YOUR_APP_SIGN;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 在项目中,选择 “TARGETS > Signing & Capabilities” 菜单,将 “Bundle Identifier” 设置为申请权限时所提供的 Bundle Id。

    1.3 安装依赖库

    • 打开终端,进入项目根目录,执行 pod 'YTKNetwork'引入依赖库;

    • 执行 pod install 命令安装依赖库。

    1.4 获取 License

    通过 ZGAvatarLicenseHelper 中的 requestLicense 接口,发起网络请求,获取鉴权 License 字符串。

    // 发起网络请求获取 License
    [ZGAvatarLicenseHelper requestLicense:^(NSString * _Nonnull license) {
        if (license.length > 0) {
    
            // 初始化 avatar Service
            [self initAvatarService: license];
        }
    }];
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    2

    初始化 AvatarService

    2.1 初始化 AvatarService 之前,请先导入以下相关的头文件,准备基础工作。

    // 引入 头文件
    #import 
    
    • 1
    • 2

    2.2 导入头文件后,调用 initWithConfig 接口,传入之前获取到的鉴权 License 字符串,初始化 AvatarService。

    // 初始化 AvatarService
    - (void) initAvatarService: (NSString*) license{
        // 创建 config
        ZegoServiceConfig *config = [[ZegoServiceConfig alloc] init];
        // 将获取到的 License 文件传入
        config.license = license;
        // 指定 AI 模型的路径
        config.AIPath = [[[NSBundle mainBundle] bundlePath] stringByAppendingString:@"/assets/AIModel.bundle"];
        // 监听初始化状态,addServiceObserver 需要在 "主线程" 执行!!!
        [[ZegoAvatarService sharedInstance] addServiceObserver:self];
    
        // 初始化 AvatarService
        [[ZegoAvatarService sharedInstance] initWithConfig:config];
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    2.3 注册 onStateChange 回调,接收初始化状态的相关回调通知。

    
    // avatarService初始化状态回调
    - (void)onStateChange:(ZegoAvatarServiceState)state {
        // SDK初始化成功
        if (state == ZegoAvatarServiceState_InitSucceed) {
            // 初始化虚拟形象
            [self initAvatar];
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    3

    创建虚拟形象

    注意:在创建虚拟人物形象时,为了简化 Character(虚拟人物形象)的初始化、序列化、数据缓存、路径拼接等功能的接入流程,ZEGO Avatar SDK 提供了 ZegoCharacterHelper 类(开源),帮助开发者快速创建人物虚拟形象,详情请参考 ZegoCharacterHelper 使用说明

    初始化 AvatarService 后,通过创建 ZegoCharacterHelper 对象,传入虚拟人物形象的外观数据(捏脸、换装、妆容等),设置视图参数(宽、高、位置等),创建一个虚拟形象。

    
    - (void) initAvatar{
        // 创建 Helper,传入基础资源的路径
        NSString *resourcePath = [[[NSBundle mainBundle] bundlePath] stringByAppendingString:@"/assets/base.bundle"];
        _characterHelper = [[ZegoCharacterHelper alloc] init:resourcePath];
    
        // 设置素材资源包地址,如果是动态下载,则传入下载的目标目录
        NSString *packagesPath = [[[NSBundle mainBundle] bundlePath] stringByAppendingString:@"/assets/Packages"];
        [_characterHelper setExtendPackagesPath:packagesPath];
    
        // 使用默认形象,以男性角色为例
        [_characterHelper setDefaultAvatar:MODEL_ID_MALE];
    
        // 创建 AvatarView
        _avatarView = [[ZegoAvatarService sharedInstance] createAvatarView:CGRectMake(0, 0, 200, 200)];
        [self.view addSubview:_avatarView];
    
        //角色上屏,请保证上屏之前设置过正确的 AvatarJson 数据,即调用过 setDefaultAvatar 或 setAvatarJson 方法。
        [_characterHelper setCharacterView:_avatarView];
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    说明:如果用户不使用默认形象,想要根据图片自动生成定制化的虚拟形象,请参考 AI 捏脸

    =======

    Avatar 功能拓展

    ========================

    我们已经知道,图像由像素组成,而像素通过记录色彩空间各分量呈现各种各样的色彩。对于 RGB 色彩空间,其三个分量 R(红)、G(绿)、B(蓝),它们之间具有相关性,对于色彩的表示来说缺一不可。

    虚拟形象创建完成后,可体验 Avatar 相关功能:


    1

    表情随动

    ZEGO Avatar SDK 提供了表情随动功能,基于领先的人脸关键点精准识别,结合面部、舌头、眼球在内的 52 种基础面部表情维度,实时捕获用户脸部的表情动作,在虚拟形象上进行实时的还原渲染。可广泛应用于社交互动、语聊直播等场景中。

    开发者请参考以下步骤,实现 “表情随动” 功能:

    1.1 开始表情检测

    • 开启表情检测前,请确认已开启摄像头权限;

    • 开发者如果使用了 ZegoCharacterHelper,则无需再调用 IZegoCharacter 的任何相关接口。

    搭建出基本的虚拟人物形象后,调用 startDetectExpression 接口,设置驱动模式为 ZegoExpressionDetectModeCamera,通过前置摄像头,开始检测表情;然后可以直接通过 ZegoCharacterHelper的 setExpression 接口设置表情,驱动当前虚拟人物的面部表情变化。

    
    // 开始表情检测
    ___weak typeof(self) weakSelf = self;
    BOOL ret = [[[ZegoAvatarService sharedInstance] getInteractEngine] startDetectExpression:ZegoExpressionDetectModeCamera callback:^(ZegoExpression *expression) {
        // 驱动虚拟人物的脸部变化
        __strong typeof(self) strongSelf = weakSelf;
        [strongSelf.characterHelper setExpression: expression];
    }];
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    1.2 停止表情检测

    将应用切换到后台运行、或退出当前页面时,需要调用 stopDetectExpression 接口,停止表情检测。

    
    // 停止表情检测
    [[[ZegoAvatarService sharedInstance] getInteractEngine] stopDetectExpression];
    
    • 1
    • 2
    • 3

    2

    语音驱动

    ZEGO Avatar SDK 提供了语音驱动功能,通过声音的声波信息,实时驱动当前虚拟人物的嘴形变化,使得虚拟形象能够和真人一样进行自然的情绪表达。

    可广泛应用于社交互动、语聊直播等场景中。

    开发者请参考以下步骤,实现 “语音驱动” 功能:

    2.1 开始语音检测

    • 开始语音检测前,请确认已开启麦克风权限;

    • 开发者如果使用了 ZegoCharacterHelper,则无需再调用 IZegoCharacter 的任何相关接口。

    搭建出基本的虚拟人物形象后,调用 startDetectExpression 接口,设置驱动模式为 ZegoExpressionDetectModeAudio,通过麦克风,开始检测声音波动;然后可以直接通过 ZegoCharacterHelper 的 setExpression 接口设置表情,驱动当前虚拟人物的嘴形变化。

    // 开始语音检测
    ___weak typeof(self) weakSelf = self;
    BOOL ret = [[[ZegoAvatarService sharedInstance] getInteractEngine] startDetectExpression:ZegoExpressionDetectModeAudio callback:^(ZegoExpression *expression) {
        // 驱动虚拟人物的嘴形变化
        __strong typeof(self) strongSelf = weakSelf;
        [strongSelf.characterHelper setExpression: expression];
    }];
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    2.2 自定义音频采集

    开发者可以调用 setCustomAudioDelegate 接口,设置自定义的音频数据采集代理(需要继承 AudioDataDelegate 实现 onStartonStop 方法)。采集到音频数据后,调用 sendAudioData 接口,发送数据。

    
    @interface ExpressAudioCaptureDelegate()
    {
        BOOL _isRunning;
    }
    @end
    
    @implementation ExpressAudioCaptureDelegate
    
    - (void)onStart{
        // 启动音频采集
        _isRunning = YES;
    }
    
    - (void)onStop{
        // 停止音频采集
        _isRunning = NO;
    }
    
    // 这是 Express 的自定义声音的前处理回调, 把数据发送给 Avatar SDK
    - (void)onProcessCapturedAudioData:(unsigned char * _Nonnull)data dataLength:(unsigned int)dataLength param:(ZegoAudioFrameParam *)param timestamp:(double)timestamp; {
        if(_isRunning){
            // data: pcm的原始数据
            // length: data的长度
            // dataType: data采集的位数  0表示16位,1表示8位
            // timeStamp: 时间戳, 从启动采集到现在经过的时间
            // sendAudioData 是父类方法, 数据透传给 Avatar SDK, RTC 的数据是 8位的, dataType 是 1
            [super sendAudioData: (void*)data  size:dataLength dataType: 1 /* RTC 给的 8bit*/ timeStamp: [super getDurationMs]/*这个方法是父类的,直接调用*/];
        }
    }
    @end
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    2.3 停止语音检测

    将应用切换到后台运行、或退出当前页面时,需要调用 stopDetectExpression 接口,停止语音检测。

    // 停止语音检测``[[[ZegoAvatarService sharedInstance] getInteractEngine] stopDetectExpression];
    
    • 1

    3

    手动捏脸

    ZEGO Avatar SDK 提供了手动捏脸功能,支持用户根据自己的审美偏好,对虚拟人物形象脸部的各个部位进行细微调节(如眼睛大小、鼻子宽窄、嘴巴大小等),融合成自定义的虚拟人物形象人脸,自由定义,打造独一无二的专属形象,可广泛应用于各类游戏场景中。

    开发者请参考以下步骤,实现 “手动捏脸” 功能:

    搭建出基本的虚拟人物形象后调用 setFaceShape 接口,传入 faceshapeID(可调整的脸部维度,请参考下表)和 value(捏脸系数)等参数,设置或修改脸部相关位置的形状。我们在 helper/ZegoCharacterHelper.h 中,同样声明了所有可支持调整的脸部维度 faceshapeID。

    // 停止语音检测
    [[[ZegoAvatarService sharedInstance] getInteractEngine] stopDetectExpression];
    
    • 1
    • 2
      /** 设置捏脸系数,faceshapeID 值参考下表,并且 ZegoCharacterHelper 内有定义好的常量,可以直接使用。*/
    [_characterHelper setFaceShape:FACESHAPE_BROW_SIZE_Y value:0.3];
    
    • 1
    • 2

    目前,支持调整的脸部维度可以点击链接查看详情:https://doc-zh.zego.im/article/14959


    4

    AI 捏脸

    ZEGO Avatar SDK 提供了AI 捏脸功能,支持通过“摄像头”或者“上传图像”的方式,结合对人脸进行海量分析和训练后的 AI 算法,识别人脸特征,再以美术设计提供的虚拟形象人模为基础,生成与真人高度还原的虚拟形象。可广泛应用于各类游戏场景中。

    开发者请参考以下步骤,实现 “AI 捏脸” 功能。

    4.1 初始化 AvatarService

    请参考 创建虚拟形象 文档,获取鉴权 License 文件;并传入正确的 AIPath,初始化 AvatarService。

    4.2 创建虚拟人物形象

    准备需要用来创建虚拟人物形象的 UIImage 图片。

    • 推荐使用摄像头拍摄图片。

    准备好图片后,调用 detectFaceFeature 接口,传入 UIImage,即可生成该图片对应的虚拟人物形象。

    / 根据传入的图片,提取人脸特征
    ZegoFaceFeature *feature = [[[ZegoAvatarService sharedInstance] getInteractEngine] detectFaceFeature:image];
    
    • 1
    • 2
    • 如果 UIImage 中检测不到人脸,调用 detectFaceFeature 接口会直接返回 nil。

    4.3 设置捏脸数据

    创建出虚拟人物形象后,调用 ZegoCharacterHelper 的 applyFaceFeature 接口,传入 feature(设置的脸部维度,可设置的维度请参考下表),设置脸部相关位置的形状。

    // 根据人脸特征,设置人物外形
    [_characterHelper applyFaceFeature:feature];
    
    • 1
    • 2

    目前,支持调整的脸部维度可以点击链接查看详情:https://doc-zh.zego.im/article/14972

    5

    妆容换装

    ZEGO Avatar SDK 提供了多种妆容配饰(如美瞳、口红、眼镜、胡子、服装等)等美术素材,支持在虚拟形象上实时渲染、自然替换,打造符合自己品味的专属形象。

    开发者请参考以下步骤,实现 “换妆容、换服装” 功能。

    目前,支持调整的维度有:眉毛、刺青、嘴唇、胡子、美瞳、眼镜、耳机、耳饰、头发、服装等。具体的支持维度和资源类型,请咨询 ZEGO 商务人员。

    开发者如果使用了 ZegoCharacterHelper,则无需再调用 IZegoCharacter 的任何相关接口。虽然 IZegoCharacter 也有同名的 setPackage 接口,但请不要直接调用。如果跳过 ZegoCharacterHelper 直接调用 IZegoCharacter 的接口,ZegoCharacterHelper 层的缓存将不再可信。

    搭建出基本的虚拟人物形象后:

    • 如果开发者把 Packages 资源包做成动态下载,则需要在使用 Packages 前,调用 ZegoCharacterHelper 的 setExtendPackagesPath 接口设置 Packages 的下载目录到参数 downloadPath,以便资源索引。

    downloadPath 需指到 Packages 文件夹,例如:/Documents/downloads/Package/。

    • 调用 setPackage 接口,传入 packageID,调整虚拟人物相关位置的外观。
    //确保换装调用前已经设置的外部 Packages 的目录
    [_characterHelper setExtendPackagesPath:downloadPath]
    /** 调用换装接口*/
    NSString *packageID = @"earphone7";  //earphone7 是一款耳机资源的目录名称,使用 Zego 提供的 Pacakges 下的目录名称即可。
    [_characterHelper setPackage:packageID];
    
    • 1
    • 2
    • 3
    • 4
    • 5

    =======

    demo 展示

    元宇宙是人类对于未来社会的美好想象,而虚拟人则是人类对于未来“Better me”的美好寄托。ZEGO 即构科技为用户定制个性化的虚拟形象,从技术底层为开发者赋能,与元宇宙生态里的所有成员一起,让元宇宙的理想进程推进得再快、再稳一些。

    ZEGO Avatar SDK的元宇宙场景技术实践,包括实现"虚拟人"自由的语音检测、自定义音频采集和停止语音检测的方法。此外,还介绍了手动捏脸、AI捏脸和妆容换装的功能。点击即构Avatar虚拟形象:文档提供了相关代码示例和接口说明,帮助开发者实现个性化的虚拟形象。

    下方是ZEGO即构科技的 Avatar 展示!

  • 相关阅读:
    现代对称密码
    spark报错:Cannot overwrite a path that is also being read from.
    7000+客户经验总结,《数字化转型实践指南》重磅发布
    应用ceph文件系统存储(ceph-13.2.10)
    Go----Go 语言基础之标识符、关键字、命名规范、变量、常量
    [DIY]自己设计微软MakeCode街机,官方开源软硬件
    git commit规范
    UNIX环境高级编程-第三章
    Intel Trust Domain Extensions(TDX)介绍
    Oracle19c安装以及问题汇总
  • 原文地址:https://blog.csdn.net/zego_0616/article/details/127747228