即构虚拟形象引擎(Zego Avatar)支持自定义管理人物的虚拟形象,通过默认的虚拟形象或者自定义生成的专有虚拟形象,以表情随动、声音驱动等方式与真人实时互动,可广泛应用于语聊直播、社交互动、在线培训等多种场景中。
在开始集成 ZegoAvatar SDK 前,请确保开发环境满足以下要求:
此步骤以如何创建新项目为例,如果是集成到已有项目,可忽略此步。
目前支持的平台架构包括:armeabi-v7a、arm64-v8a。
请前往 下载 页面,获取最新版本的 SDK。
解压 SDK 压缩包,将 ZegoAvatar 的制品包中的 ZegoAvatar.aar 拷贝至自己的项目目录下,如 “app/libs”。

添加 SDK 引用。进入到 “app” 目录,打开 “build.gradle” 文件,在 “dependencies” 节点引入 “libs” 下所有的 jar。

implementation fileTree(dir: 'libs', include: ['*.jar', "*.aar"]) //通配引入
根据实际应用需要,设置应用所需权限。
进入 “app/src/main” 目录,打开 “AndroidManifest.xml” 文件,添加权限。
<!-- SDK 必须使用的权限 -->
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<!-- App 需要使用的部分权限 -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-feature
android:glEsVersion="0x00020000"
android:required="true" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />
因为 Android 6.0 在一些比较重要的权限上要求必须申请动态权限,不能只通过 “AndroidMainfest.xml” 文件申请静态权限。因此还需要参考执行如下代码,其中 “requestPermissions” 是 “Activity” 的方法。
String[] permissionNeeded = {
"android.permission.CAMERA"};
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (ContextCompat.checkSelfPermission(this, "android.permission.CAMERA") != PackageManager.PERMISSION_GRANTED) {
requestPermissions(permissionNeeded, 101);
}
}
| 必要性 | 权限 | 权限说明 | 申请原因 |
|---|---|---|---|
| 必要权限 | CAMERA | 访问相机权限。 | 通过摄像头画面推理面部表情时,需要使用该权限。 |
| RECORD_AUDIO | 录制音频权限。 | 通过声音波动推理面部表情时,需要使用该权限。 | |
| WRITE_EXTERNAL_STORAGE | 内置 SDK 写权限。 | SDK 会将日志和相关配置文件保存在内置 SDK 内。需要保存截图或录制的视频时,也需要使用该权限。 | |
| 非必要权限 | INTERNET | 访问网络权限。 | SDK 鉴权获取时,需要使用该权限。 |
| READ_EXTERNAL_STORAGE | 文件读取权限。 | SDK 需要读取资源包时,需要使用该权限。 |
在 “proguard-rules.pro” 文件中,为 SDK 添加 -keep 类的配置,防止混淆 SDK 公共类名称。
-keep class **.zego.**{*;}
使用 Avatar 提供的各项 AI 能力之前,需要导入相应的资源包,请前往 下载 页面,获取下列资源包。
开发者可以通过 动态下载 或 从本地添加 两种方式,导入资源包。
| 资源名称 | 说明 | 资源大小 | 是否支持 动态下载 |
建议下载时机 |
|---|---|---|---|---|
| AIModel.bundle | Avatar 的 AI 模型资源。当使用表情随动、声音随动、AI 捏脸等能力时,必须先将该资源的绝对路径设置给 Avatar SDK。 |
|
是 | 必须在 ZegoAvatarService 初始化前完成下载。 |
| base.bundle | 美术资源,包含基础 3D 人物模型资源、资源映射表、人物模型默认外形等。 |
|
是 | 必须在创建 ZegoCharacterHelper 前完成下载。 |
| Packages | 美妆、挂件、装饰等资源。 | 每个资源 200 KB ~ 1 MB 不等,跟资源复杂度相关。 | 是 | 建议在需要使用相关资源时再去下载,不使用时可不下载,减少对本地存储空间的占用。 |
Packages 中包含了部分美术资源,开发者如有需要,请联系 ZEGO 商务人员,获取所有的美术资源。
请前往 下载 页面,获取相关的资源包。
解压获取到的资源包,找到 “assets” 文件夹,拷贝到自己创建项目的 “assets” 文件夹下。



运行项目时,将 “AIModel.bundle”、“base.bundle” 、"Packages" 文件,通过以下代码,拷贝到设备的私有目录(/data/data/包名/files)下。(注意:Android 系统的 assets 文件夹只能读取。)
AssetsFileTransfer.copyAssetsDir2Phone(this.getApplication(),
"AIModel.bundle"/*apk 里的assets 根目录*/, "assets"/* sd 卡里的目录, 值为:getFilesDir().getAbsolutePath() + File.separator + destPath */);
AssetsFileTransfer.copyAssetsDir2Phone(this.getApplication(),
"base.bundle", "assets");
AssetsFileTransfer.copyAssetsDir2Phone(this.getApplication(),
"Packages", "assets");
/**
* 把assets/${filePath}目录中的所有内容拷贝到 手机的Storage的${destPath}/目录中
*
* @param activity activity 使用CopyFiles类的Activity
* @param filePath String 相对于Android APK内的assets目录的文件路径,如:AIModel.bundle
* @param destPath String 拷贝的目标, 如:/data/data/包名/files/assets/
*/
public static void copyAssetsDir2Phone(Context activity, String filePath, String destPath) {
try {
String[] fileList = activity.getAssets().list(filePath);
if (fileList.length > 0) {//如果是目录
File file = new File(activity.getFilesDir().getAbsolutePath() + File.separator + destPath + File.separator + filePath);
if (file.exists()) {
deleteAllFiles(file);
}
file.mkdirs();//如果文件夹不存在,则递归
for (String fileName : fileList) {
filePath = filePath + File.separator + fileName;
copyAssetsDir2Phone(activity, filePath, destPath);
filePath = filePath.substring(0, filePath.lastIndexOf(File.separator));
Log.i(TAG, filePath);
}
} else {//如果是文件
InputStream inputStream = activity.getAssets().open(filePath);
File file = new File(activity.getFilesDir().getAbsolutePath() + File.separator + destPath + File.separator + filePath);
if (file.exists()) {
boolean delete = file.delete();
}
if (!file.exists() || file.length() == 0) {
FileOutputStream fos = new FileOutputStream(file);
int len = -1;
byte[] buffer = new byte[1024];
while ((len = inputStream.read(buffer)) != -1) {
fos.write(buffer, 0, len);
}
fos.flush();
inputStream.close();
fos.close();
}
}
} catch (IOException e) {
Log.e(TAG, "copy file faild, src:" + filePath + " dest:" + destPath);
e.printStackTrace();
}
}
拷贝资源后,在移动设备上运行时,会存在如下的结构。注意:不同的移动设备,getFilesDir().getAbsolutePath() 返回的目录可能不一样。这里以华为手机为例,其返回的是:/data/data/im.zego.zegoavatarexample。

使用某一功能时,在对应接口中,传入接口要求的资源的 绝对路径 即可。
本节介绍如何使用 ZegoAvatar SDK 实现基本的图像处理功能,API 调用时序如下图:

ZEGO Avatar 目前使用 在线鉴权 的方式获取 License 授权文件。
请先在 ZEGO 控制台 创建项目,并申请有效的 AppID,详情请参考 控制台 - 项目管理 中的“项目信息”。
请联系 ZEGO 商务人员,提供申请到的 AppID,以及自己项目的 Bundle Id,获取鉴权需要使用的 AppSign,并开通相关权限。
请将从 下载 获取到的示例源码中的 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;
在项目中,选择 “TARGETS > Signing & Capabilities” 菜单,将 “Bundle Identifier” 设置为申请 AppID 时所提供的 Bundle Id。

打开终端,进入项目根目录,执行 pod 'YTKNetwork',引入依赖库。
执行 pod install 命令安装依赖库。
通过 ZGAvatarLicenseHelper 中的 requestLicense 接口,发起网络请求,获取鉴权 License 字符串。
// 发起网络请求获取 License
[ZGAvatarLicenseHelper requestLicense:^(NSString * _Nonnull license) {
if (license.length > 0) {
// 初始化 avatar Service
[self initAvatarService: license];
}
}];
初始化 AvatarService 之前,请先导入以下相关的头文件,准备基础工作。
// 引入 头文件
#import <ZegoAvatar/ZegoAvatarService.h>
导入头文件后,调用 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];
}
注册 onStateChange 回调,接收初始化状态的相关回调通知。
// avatarService初始化状态回调
- (void)onStateChange:(ZegoAvatarServiceState)state {
// SDK初始化成功
if (state == ZegoAvatarServiceState_InitSucceed) {
// 初始化虚拟形象
[self initAvatar];
}
}
在创建虚拟人物形象时,为了简化 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];
//角色上屏
[_characterHelper setCharacterView:_avatarView];
}
在VMware16.2.4安装Ubuntu一、安装VMware1.打开VMwareWorkstationPro官网,点击即可进入。2.进入后向下滑动找到Workstation16ProforWindows,点击立即下载。3.下载完成,文件大小615MB,如下图:4.鼠标右击,以管理员身份运行。5.点击下一步6.勾选条款,点击下一步7.先勾选,再点击下一步8.去掉勾选,点击下一步9.点击下一步10.点击安装11.点击许可证12.在百度上搜索VM16许可证,复制填入,然后点击输入即可,亲测有效。13.点击完成14.重启系统,点击是15.双击VMwareWorkstationPro图标,进入虚拟机主
需求:要创建虚拟机,就需要给他提供一个虚拟的磁盘,我们就在/opt目录下创建一个10G大小的raw格式的虚拟磁盘CentOS-7-x86_64.raw命令格式:qemu-imgcreate-f磁盘格式磁盘名称磁盘大小qemu-imgcreate-f磁盘格式-o?1.创建磁盘qemu-imgcreate-fraw/opt/CentOS-7-x86_64.raw10G执行效果#ls/opt/CentOS-7-x86_64.raw2.安装虚拟机使用virt-install命令,基于我们提供的系统镜像和虚拟磁盘来创建一个虚拟机,另外在创建虚拟机之前,提前打开vnc客户端,在创建虚拟机的时候,通过vnc
有没有办法快速将表格格式的ruby哈希打印到文件中?如:keyAkeyBkeyC...1232343451253474456...其中散列的值是不同大小的数组。还是使用双循环是唯一的方法?谢谢 最佳答案 试试我写的这个gem(在表中打印散列、ruby对象、ActiveRecord对象):http://github.com/arches/table_print 关于ruby-如何以表格格式快速打印Ruby哈希值?,我们在StackOverflow上找到一个类似的问题:
3月26日,映宇宙(HK:03700,即“映客”)发布截至2022年12月31日的2022年度业绩财务报告。财报显示,映宇宙2022年的总营收为63.19亿元,较2021年同期的91.76亿元下降31.1%。2022年,映宇宙的经营亏损为4698.7万元,2021年同期则为净利润4.57亿元;期内亏损(净亏损)为1.68亿元,2021年同期的净利润为4.33亿元;非国际财务报告准则经调整净利润为3.88亿元,2021年同期为4.82亿元,同比下降19.6%。 映宇宙在财报中表示,收入减少主要是由于行业竞争加剧,该集团对旗下产品采取更为谨慎的运营策略以应对市场变化。不过,映宇宙的毛利率则有所提升
电脑启动出现显示器黑屏是一个相当常见的问题。如果您遇到了这个问题,不要惊慌,因为它有很多可能的原因,可以采取一些简单的措施来解决它。在本文中,小编将介绍下面4种常见的电脑启动后显示器黑屏的原因,排查这些原因,快速解决! 演示机型:联想Ideapad700-15ISK-ISE系统版本:Windows10一、显示器问题如果出现电脑启动后显示器黑屏的情况。那么首先您需要检查一下显示器是否正常工作。您可以通过更换另一个显示器或将当前显示器连接到另一台计算机来检查显示器是否存在问题。如果问题仍然存在,那么您可以排除显示器故障的可能性。 二、显卡问题如果您的电脑配备了独立显卡,那么显卡故障也可能是导致电脑
参考文章搭建文章gitte源码在线体验可以注册两个号来测试演示图:一.整体介绍 介绍SignalR一种通讯模型Hub(中心模型,或者叫集线器模型),调用这个模型写好的方法,去发送消息。 内容有: ①:Hub模型的方法介绍 ②:服务器端代码介绍 ③:前端vue3安装并调用后端方法 ④:聊天室样例整体流程:1、进入网站->调用连接SignalR的方法2、与好友发送消息->调用SignalR的自定义方法 前端通过,signalR内置方法.invoke() 去请求接口3、监听接受方法(渲染消息)通过new signalR.HubConnectionBuilder().on
我这个模型:classBunny每当我提交一个表单来创建这个模型时,我都会收到以下错误:#的未定义方法“number_before_type_cast” 最佳答案 我通过将此方法添加到我的Bunny模型中解决了这个问题:defnumber_before_type_castnumberend我不喜欢它,但我想在有人发布更好的解决方案之前它会起作用。 关于ruby-on-rails-Rails验证虚拟属性,我们在StackOverflow上找到一个类似的问题: h
在Rails3.x应用程序中,我正在使用net::ssh并向远程pc运行一些命令。我想向用户的浏览器显示实时日志。比如,如果两个命令在net中运行::ssh执行即echo"Hello",echo"Bye"被传递然后"Hello"应该在执行后立即显示在浏览器中。这是代码我在rubyonrails应用程序中使用ssh连接和运行命令Net::SSH.start(@servers['local'],@machine_name,:password=>@machine_pwd,:timeout=>30)do|ssh|ssh.open_channeldo|channel|channel.requ
mutationtesting遇到一个问题是它很慢,因为默认情况下您会为每个生成的突变执行完整的测试运行(测试文件或一组测试文件)。加快突变测试的一种方法是,一旦遇到单一故障(但仅在突变测试期间),就停止对给定突变体的测试运行。更好的做法是让变异测试者记住杀死最后一个变异体的第一个测试是什么,并将其首先交给下一个变异体。ruby中是否有任何东西可以做这些事情,或者我最好的选择是开始猴子修补?(是的,我知道单元测试应该很快。显示所有失败的测试在突变测试之外很有用,因为它不仅可以帮助您识别出问题,还可以查明哪里出了问题)编辑:我目前正在对测试/单元使用heckle。如果测试/单元不可能记住
这里是初级程序员,只是想了解Ruby背后的过程sort使用飞船操作符时的方法.希望有人能帮忙。在以下内容中:array=[1,2,3]array.sort{|a,b|ab}...我明白sort一次比较一对数字,然后返回-1如果a属于b之前,0如果它们相等,或者1如果a应该遵循b.但是在降序排序的情况下,像这样:array.sort{|a,b|ba}...到底发生了什么?是否sort还是比较ab然后翻转结果?或者它是在解释return的-1,0和1具有相反的行为?换句话说,为什么要像这样将变量放在block中:array.sort{|b,a|ba}...结果与第一个示例中的排序模式相同?