前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >基于NVIDIA Jetson AGX Orin和Audio2Face做一个AI聊天数字人

基于NVIDIA Jetson AGX Orin和Audio2Face做一个AI聊天数字人

作者头像
GPUS Lady
发布2024-05-07 10:11:30
2060
发布2024-05-07 10:11:30
举报
文章被收录于专栏:GPUS开发者GPUS开发者

本文教程来自:

在当今的数字化时代,逼真会说话的虚拟形象(或称为“avatar”)已经成为一种全新的交流和表达方式。在本篇文章里,博主介绍如何利用NVIDIA Jetson AGX Orin 开发者套件、NVIDIA Omniverse平台以及强大的Unreal Engine虚幻引擎制作一个的逼真会说话的avatar。

原文地址:www.hackster.io/shahizat/ai-powered-photorealistic-talking-avatar-abac41

项目背景

想象一下,拥有一个栩栩如生的数字化身(avatar),它不仅看起来像真人,而且听起来和行动起来也像真人。这不再是科幻小说的领域,而是由NVIDIA Jetson AGX Orin Developer Kit、NVIDIA Omniverse和Unreal Engine等尖端技术实现的现实。

在这个项目中,我们将深入探索逼真的会说话的化身世界,并探讨这些技术是如何结合在一起,创造出一种真正身临其境的体验的。基本上,我们可以使用化身来构建对话代理、虚拟助手、聊天机器人等。无论您是开发者还是技术爱好者,这个项目都适合您。

项目架构

以下是该系统的工作原理:

系统从麦克风的音频输入开始。该输入由运行在NVIDIA Jetson AGX Orin开发者套件上的OSC客户端捕获。客户端利用Nvidia Riva文本转语音技术(TTS)、Nvidia Riva自动语音识别(ASR)以及大型语言模型进行推断。处理后的音频数据随后通过由达斯汀·富兰克林(@dusty-nv)开发的名为Llamaspeak的Python应用程序传递到OSC服务器。OSC服务器使用Audio2Face从音频生成面部动画。最后,在配备RTX显卡的PC上运行的虚幻引擎5(Unreal Engine 5)会渲染出最终的面部动画输出。

此架构展示了一个复杂的工作流程,该流程将音频输入转换为面部动画。它利用了语音识别、文本转语音和唇音同步等先进技术,以及强大的计算硬件(NVIDIA Jetson AGX Orin)和先进的渲染软件(虚幻引擎5)。

Nvidia Omniverse Audio2Face

让我们首先讨论Nvidia Omniverse Audio2Face,这是一项革命性的技术,它能够创建具有逼真面部表情和动作的逼真数字化身。它是一种基于音频输入为3D角色生成面部动画的AI工具。它可以处理预先录制的语音或实时音频馈送,使其适用于各种应用。Omniverse Audio2Face最好的地方在于它易于使用。您只需提供一个音频文件或实时音频馈送,该工具即可自动生成逼真的面部表情。

此外,此工具可以与第三方渲染应用程序(如虚幻引擎5)集成。开发人员可以轻松地将面部动画集成到Metahuman角色中,从而简化动画工作流程。

Audio2Face适用于配备Nvidia RTX GPU的Windows和Linux用户。可以从Nvidia Omniverse平台下载它。

请从此处下载Omniverse启动器。www.nvidia.com/en-us/omniverse/download/

下载后,双击安装程序文件。

点击“Exchange”选项卡。 在“应用”区域中搜索Audio2Face。 点击Audio2Face的“安装”按钮。

安装完毕后,您可以点击“Exchange”选项卡中的“启动”来打开Audio2Face。

导航到Audio2Face安装目录下的exts\omni.audio2face.exporter\config文件夹。 在文本编辑器中打开extension.toml文件。 将以下内容添加到文件底部:

代码语言:javascript
复制
[python.pipapi]
requirements=['python-osc']
use_online_index=true

Python-osc是一个简单的Python中的OpenSoundControl实现,为简单的OSC客户端和OSC服务器提供支持。Open Sound Control(OSC)是音频行业中许多领域常用的开放协议。它主要用于在客户端之间网络传输通用音频数据,尽管它也可以用于非音频数据。 运行以下代码以检查python-osc库是否已在Audio2Face环境中正确安装。

然后导航到安装目录下的exts\omni.audio2face.exporter\omni\audio2face\exporter\scripts文件夹。 在文本编辑器中打开facsSolver.py脚本。此脚本用于使用Open Sound Control协议在Audio2Face和虚幻引擎之间建立通信通道。 在脚本中,添加此行代码以创建一个UDP客户端:

代码语言:javascript
复制
from pythonosc import udp_client
self.client = udp_client.SimpleUDPClient('127.0.0.1', 5008)

然后添加以下代码片段。

代码语言:javascript
复制
mh_ctl_list = [
['CTRL_expressions_browDownR', "browLowerR", 1.0],  
['CTRL_expressions_browDownL', "browLowerL", 1.0], 

['CTRL_expressions_browLateralR', "browLowerR", 1.0],
['CTRL_expressions_browLateralL', "browLowerL", 1.0],

['CTRL_expressions_browRaiseinR', "innerBrowRaiserR", 0.5],
['CTRL_expressions_browRaiseinL', "innerBrowRaiserL", 0.5], 

['CTRL_expressions_browRaiseouterR', "innerBrowRaiserR", 0.5], 
['CTRL_expressions_browRaiseouterL', "innerBrowRaiserL", 0.5],

['CTRL_expressions_eyeLookUpR', "eyesLookUp", 1.0, "eyesLookDown", -1.0],
['CTRL_expressions_eyeLookDownR', "eyesLookUp", 1.0, "eyesLookDown", -1.0],
['CTRL_expressions_eyeLookUpL', "eyesLookUp", 1.0, "eyesLookDown", -1.0],
['CTRL_expressions_eyeLookDownL', "eyesLookUp", 1.0, "eyesLookDown", -1.0],


['CTRL_expressions_eyeLookLeftR', "eyesLookLeft", 1.0, "eyesLookRight", -1.0],
['CTRL_expressions_eyeLookRightR', "eyesLookLeft", 1.0, "eyesLookRight", -1.0],
['CTRL_expressions_eyeLookRightL', "eyesLookLeft", 1.0, "eyesLookRight", -1.0],
['CTRL_expressions_eyeLookRightL', "eyesLookLeft", 1.0, "eyesLookRight", -1.0],


['CTRL_expressions_eyeBlinkR', "eyesCloseR", 1.0, "eyesUpperLidRaiserR", -1.0], 
['CTRL_expressions_eyeBlinkL', "eyesCloseR", 1.0, "eyesUpperLidRaiserR", -1.0], 

['CTRL_expressions_eyeSquintinnerR', "squintR", 1.0], 
['CTRL_expressions_eyeSquintinnerL', "squintL", 1.0],

['CTRL_expressions_eyeCheekraiseR', "cheekRaiserR", 1.0], 
['CTRL_expressions_eyeCheekraiseL', "cheekRaiserL", 1.0],

['CTRL_expressions_mouthCheekSuckR', "cheekPuffR", 0.5], 
['CTRL_expressions_mouthCheekBlowR', "cheekPuffR", 0.5], 

['CTRL_expressions_mouthCheekSuckL', "cheekPuffL", 0.5],
['CTRL_expressions_mouthCheekBlowL', "cheekPuffL", 0.5],

['CTRL_expressions_noseNostrilDilateR', "noseWrinklerR", 1.0],
['CTRL_expressions_noseNostrilCompressR', "noseWrinklerR", 1.0],
['CTRL_expressions_noseWrinkleR', "noseWrinklerR", 1.0],
['CTRL_expressions_noseNostrilDepressR', "noseWrinklerR", 1.0],

['CTRL_expressions_noseNostrilDilateL', "noseWrinklerL", 1.0],
['CTRL_expressions_noseNostrilCompressL', "noseWrinklerL", 1.0],
['CTRL_expressions_noseWrinkleL', "noseWrinklerL", 1.0],
['CTRL_expressions_noseNostrilDepressL', "noseWrinklerL", 1.0],


['CTRL_expressions_jawOpen', "jawDrop", 1.0, "jawDropLipTowards", 0.6],

['CTRL_R_mouth_lipsTogetherU', "jawDropLipTowards", 1.0],
['CTRL_L_mouth_lipsTogetherU', "jawDropLipTowards", 1.0],
['CTRL_R_mouth_lipsTogetherD', "jawDropLipTowards", 1.0],
['CTRL_L_mouth_lipsTogetherD', "jawDropLipTowards", 1.0],

['CTRL_expressions_jawFwd', "jawThrust", -1.0],
['CTRL_expressions_jawBack', "jawThrust", -1.0],

['CTRL_expressions_jawRight', "jawSlideLeft", -1.0, "jawSlideRight", 1.0],
['CTRL_expressions_jawLeft', "jawSlideLeft", -1.0, "jawSlideRight", 1.0],

['CTRL_expressions_mouthLeft', "mouthSlideLeft", 0.5, "mouthSlideRight", -0.5],
['CTRL_expressions_mouthRight', "mouthSlideLeft", 0.5, "mouthSlideRight", -0.5],

['CTRL_expressions_mouthDimpleR', "dimplerR", 1.0], 
['CTRL_expressions_mouthDimpleL', "dimplerL", 1.0],

['CTRL_expressions_mouthCornerPullR', "lipCornerPullerR", 1.0], 
['CTRL_expressions_mouthCornerPullL', "lipCornerPullerL", 1.0], 

['CTRL_expressions_mouthCornerDepressR', "lipCornerDepressorR", 1.0], 
['CTRL_expressions_mouthCornerDepressL', "lipCornerDepressorL", 1.0],

['CTRL_expressions_mouthStretchR', "lipStretcherR", 1.0], 
['CTRL_expressions_mouthStretchL', "lipStretcherL", 1.0], 

['CTRL_expressions_mouthUpperLipRaiseR', "upperLipRaiserR", 1.0], 
['CTRL_expressions_mouthUpperLipRaiseL', "upperLipRaiserL", 1.0],

['CTRL_expressions_mouthLowerLipDepressR', "lowerLipDepressorR", 1.0], 
['CTRL_expressions_mouthLowerLipDepressL', "lowerLipDepressorR", 1.0],

['CTRL_expressions_jawChinRaiseDR', "chinRaiser", 1.0], 
['CTRL_expressions_jawChinRaiseDL', "chinRaiser", 1.0],

['CTRL_expressions_mouthLipsPressR', "lipPressor", 1.0], 
['CTRL_expressions_mouthLipsPressL', "lipPressor", 1.0],

['CTRL_expressions_mouthLipsTowardsUR', "pucker", 1.0], 
['CTRL_expressions_mouthLipsTowardsUL', "pucker", 1.0], 

['CTRL_expressions_mouthLipsTowardsDR', "pucker", 1.0], 
['CTRL_expressions_mouthLipsTowardsDL', "pucker", 1.0], 

['CTRL_expressions_mouthLipsPurseUR', "pucker", 1.0], 
['CTRL_expressions_mouthLipsPurseUL', "pucker", 1.0], 

['CTRL_expressions_mouthLipsPurseDR', "pucker", 1.0], 
['CTRL_expressions_mouthLipsPurseDL', "pucker", 1.0],

['CTRL_expressions_mouthFunnelUR', "funneler", 1.0], 
['CTRL_expressions_mouthFunnelUL', "funneler", 1.0], 

['CTRL_expressions_mouthFunnelDL', "funneler", 1.0], 
['CTRL_expressions_mouthFunnelDR', "funneler", 1.0],

['CTRL_expressions_mouthPressUR', "lipSuck", 1.0], 
['CTRL_expressions_mouthPressUL', "lipSuck", 1.0], 

['CTRL_expressions_mouthPressDR', "lipSuck", 1.0], 
['CTRL_expressions_mouthPressDL', "lipSuck", 1.0]
]

facsNames = [
	"browLowerL",
	"browLowerR",
	"innerBrowRaiserL",
	"innerBrowRaiserR",
	"outerBrowRaiserL",
	"outerBrowRaiserR",
	"eyesLookLeft",
	"eyesLookRight",
	"eyesLookUp",
	"eyesLookDown",
	"eyesCloseL",
	"eyesCloseR",
	"eyesUpperLidRaiserL",
	"eyesUpperLidRaiserR",
	"squintL",
	"squintR",
	"cheekRaiserL",
	"cheekRaiserR",
	"cheekPuffL",
	"cheekPuffR",
	"noseWrinklerL",
	"noseWrinklerR",
	"jawDrop",
	"jawDropLipTowards",
	"jawThrust",
	"jawSlideLeft",
	"jawSlideRight",
	"mouthSlideLeft",
	"mouthSlideRight",
	"dimplerL",
	"dimplerR",
	"lipCornerPullerL",
	"lipCornerPullerR",
	"lipCornerDepressorL",
	"lipCornerDepressorR",
	"lipStretcherL",
	"lipStretcherR",
	"upperLipRaiserL",
	"upperLipRaiserR",
	"lowerLipDepressorL",
	"lowerLipDepressorR",
	"chinRaiser",
	"lipPressor",
	"pucker",
	"funneler",
	"lipSuck"
]



for i in range(len(mh_ctl_list)):
	ctl_value = 0
	numInputs = (len(mh_ctl_list[i])-1) // 2
	for j in range(numInputs):
		weightMat = outWeight.tolist()
		poseIdx = facsNames.index(mh_ctl_list[i][j*2+1])
		ctl_value += weightMat[poseIdx] * mh_ctl_list[i][j*2+2]
	
	print(mh_ctl_list[i][0], ctl_value)
	self.client.send_message('/' + mh_ctl_list[i][0], ctl_value)
	
return outWeight

总的来说,此代码片段会根据音频输入转换各种面部表情的权重值,并向虚幻引擎发送控制信号,以便相应地驱动3D角色的面部动画。

然后,将“male_bs_arkit.usd”文件拖放到插件窗口中。该文件包含男性角色脸部的混合变形数据。

现在请进入Audio2Face插件中的“A2F数据转换”部分,这个区域能让您为角色设定输入的动画数据和混合变形网格。

在“A2F数据转换”区域中,请从下拉菜单里选择“输入动画”以及“混合变形网格”。这样设置后,Audio2Face就能利用“male_bs_arkit.usd”文件中的混合变形数据来生成一个可由音频输入驱动的网格了。

最后,点击“设置混合变形解决方案”按钮,将混合变形数据应用到网格上并启用动画。点击此按钮后,您应该会看到角色的脸部开始根据男性形状产生动画效果。

在Audio2Face中播放音频文件,观察角色的脸部是否会随着音频进行相应的动画响应。

Unreal Engine与MetaHumans

Unreal Engine是由Epic Games开发的一款功能强大且多功能的实时3D创作工具。它主要用于视频游戏的开发。

MetaHuman Creator是一个在线的、用户友好的3D设计工具,用于创建高度逼真的数字人,这些数字人可以在Unreal Engine中进行动画处理。它允许任何人在短短几秒钟内创建出定制的、逼真的AI头像。

打开Unreal Engine并创建一个新的Unreal Engine项目。

然后转到“编辑”->“插件”,并启用OSC服务器和Apple ARKit插件。

OSC插件支持应用与设备之间的通信,这对于从外部源接收动画数据至关重要。

Apple ARKit可在引擎内提供增强现实体验,有可能会提升您的项目效果。

OSC服务器充当了发送给Unreal Engine本地实例的消息的监听端点。

重新启动Unreal Engine。然后访问Quixel Bridge。

Quixel Bridge是连接Unreal Engine和各种内容库(包括MetaHuman Creator)的桥梁。

导入您的MetaHuman。

您可以导入在MetaHuman Creator中创建的MetaHuman,也可以从Quixel Bridge中提供的50多个预制模型中进行选择。

按“添加”按钮将MetaHuman模型导入到场景中。

将模型从内容浏览器拖放到角色蓝图中。

然后打开MetaHuman蓝图。这涉及创建定义角色运动和行为的可视化脚本。

蓝图是Unreal Engine中的可视化脚本工具,它允许您定义角色的行为和功能。

根据蓝图的类型,每个蓝图可以包含一个或多个图表,这些图表定义了蓝图特定方面的实现。在这里,我们创建了一个OSC服务器,用于从端口5008的远程节点接收输入数据。

此蓝图专门处理MetaHuman角色的面部动画和控制。编译并保存动画蓝图。

您已成功将MetaHumans集成到您的Unreal Engine项目中。现在,我们可以在项目中为它们添加动画,将它们添加到场景中,并赋予它们生命。

整合所有内容

llamaspeak是由英伟达(Nvidia)的达斯汀·富兰克林(Dustin Franklin)开发的一种基于网络的语音助手实现。它能够通过RIVA ASR理解口语,使用LLM处理它,并通过RIVA TTS生成语音响应,为在NVIDIA Jetson板上使用类似ChatGPT的大型语言模型的用户提供对话体验。

现在我们可以将所有部分组合在一起并运行它。

要在带有RTX显卡的Windows机器上运行Audio2Face,请按照以下步骤操作:

在Windows机器上打开命令提示符。通过运行以下命令导航到包含Audio2Face应用程序的目录:

代码语言:javascript
复制
cd C:\Users\admin\AppData\Local\ov\pkg\audio2face-2022.2.1

通过执行以下命令在无头模式下启动Audio2Face

代码语言:javascript
复制
audio2face_headless.kit.bat

无头模式是Audio2Face的一项功能,它允许您无需图形用户界面即可运行程序。

执行命令后,您将看到几行输出,指示Audio2Face运行所需的各种扩展的启动。启动过程完成后,Audio2Face管道就可以使用了。

接下来,在Nvidia Jetson AGX Orin 64GB上,通过运行以下命令登录到您的Docker帐户:

代码语言:javascript
复制
docker login

然后,在终端中运行命令bash riva来启动Nvidia Riva服务器。

代码语言:javascript
复制
bash riva

执行以下命令来启动text-generation-webui服务:

代码语言:javascript
复制
./run.sh --workdir /opt/text-generation-webui $(./autotag text-generation-webui:1.7) \
python3 server.py --listen --verbose --api \
--model-dir=/data/models/text-generation-webui \
--model=mistral-7b-instruct-v0.2.Q4_K_M.gguf \
--loader=llamacpp \
--n-gpu-layers=128 \
--n_ctx=4096 \
--n_batch=4096 \
--threads=$(($(nproc) - 2))

这将使用指定的Mistral 7B Instruct模型和配置启动text-generation-webui服务。

运行以下命令来执行Llamaspeak应用程序的run.sh脚本:

代码语言:javascript
复制
./run.sh --workdir=/opt/llamaspeak \
--env SSL_CERT=/data/cert.pem \
--env SSL_KEY=/data/key.pem \
$(./autotag llamaspeak) \
python3 chat.py --verbose

之后,系统会提示您是否拉取一个兼容的容器。请按照提示操作。

代码语言:javascript
复制
Found compatible container dustynv/llamaspeak:r35.4.1 (2023-12-05, 5.0GB) - would you like to pull it? [Y/n] n

Couldn't find a compatible container for llamaspeak, would you like to build it? [y/N]y

如果未找到容器,当提示构建容器时,请输入y进行构建。

代码语言:javascript
复制
running ASR service (en-US)
-- running TTS service (en-US, English-US.Female-1)
-- running AudioMixer thread
-- starting webserver @ 0.0.0.0:8050
-- running LLM service (mistral-7b-instruct-v0.2.Q4_K_M.gguf)
 * Serving Flask app 'webserver'
 * Debug mode: on
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
 * Running on all addresses (0.0.0.0)
 * Running on https://127.0.0.1:8050
 * Running on https://10.1.199.193:8050

构建成功后,您将看到表示音频混合器线程、Web服务器和LLM服务正在运行的消息。

打开Web浏览器并导航到https://127.0.0.1:8050以访问text-generation-webui应用程序。

音频输入提示将由Llamaspeak处理,并在我们的Windows PC上的Unreal Engine项目中使用以驱动动画过程。Windows上的Unreal Engine根据处理后的音频和文本从管道接收动画数据。

在Windows PC上的Unreal Engine选项卡中,点击“播放”按钮来启动动画过程。

观看Avatar的实际操作演示!在下面的演示中,您将看到用户与Unreal Engine中的MetaHuman角色进行互动。

如您在演示中所见,这些MetaHumans不仅在视觉上令人惊叹,它们还可以与用户进行实时交流和互动。上述演示展示了用户使用英伟达Omniverse Audio2Face和英伟达Jetson AGX Orin开发者工具包,在Unreal Engine中与MetaHuman角色进行互动。想象一下,创建可以与用户进行对话的聊天机器人、教育助手,甚至是游戏中的角色。请根据您的需求自由定制应用程序。

整个代码:GitHub - shahizat/jetson_avatar: AI-Powered Photorealistic Talking Avatar

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2024-05-06,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 GPUS开发者 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 项目背景
  • 项目架构
  • Nvidia Omniverse Audio2Face
  • Unreal Engine与MetaHumans
  • 整合所有内容
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档