Kubernetes & Omniverse 动画管线工作流#

Kubernetes workflow setup overview (1x Animation Graph microservice, 1x Omniverse Renderer microservice, 1x Audio2Face-3D microservice).

在此设置中,您将在 Kubernetes 集群中运行微服务,该集群支持两个独立的头像动画流实例。

工作流配置包含以下组件

  • Audio2Face-3D 微服务:将语音音频转换为面部动画,包括口型同步

  • 动画图 微服务:管理和混合动画状态

  • Omniverse 渲染器 微服务:渲染器,根据加载的头像场景可视化动画数据

  • Gstreamer 客户端:捕获并显示图像和音频流数据作为用户前端

  • 头像场景:3D 场景和头像模型数据的集合,在动画图和 Omniverse 渲染器微服务之间共享,并从 NGC 资源中拉取

先决条件#

在开始之前,请确保已安装并检查开发设置中的所有先决条件。

此外,本节假设满足以下先决条件

  • 您有一个可用的 Kubernetes 集群

  • 您已安装 Kubectl

  • 您已安装 Helm

  • 您有权访问 NVAIE,这是下载相关微服务所必需的

注意

  • 请注意,minikubemicrok8s 版本 1.291.30 已报告驱动程序问题。如果您遇到错误 Cuda failure: CUDA driver version is insufficient for CUDA runtime version,请考虑切换到 microk8s 1.24,经验证该版本可以正常工作。

最后,您需要访问公共 NGC 目录,这是下载 Avatar Configurator 所必需的。

硬件要求#

本指南假设您有足够的 GPU 资源。单个渲染器将消耗高达 8 GB 的 GPU 内存(取决于头像场景)。要运行如管线中所示的两个渲染器,我们建议使用两个 GPU。或者,您可以配置设置为在单个 GPU 上仅运行一个渲染器(请参阅调整 UCS 应用程序以适应单渲染器和 GPU)。

每个组件都有自己的硬件要求。工作流的要求是其组件的总和。

下载 UCS 应用程序文件#

下载以下文件并将它们放在一个空的 ucs_apps 目录中

更新 animation_pipeline_params.yaml 文件的 avatar-renderer-a.livestream.host 属性以使用您自己的 IP 地址(hostname -I 将显示您的 IP 地址)。对 avatar-renderer-b 执行相同的操作。

注意

上述配置假设您有权访问两个 GPU,并且它为每个 GPU 部署一个渲染器。

调整 UCS 应用程序以适应单渲染器和 GPU#

为了减少所需的 GPU 资源,您可以通过注释掉包含 avatar-renderer-b 的所有部分和行来调整 UCS 应用程序配置,以在单个 GPU 上运行一个渲染器

配置资源下载器#

动画图微服务和 Omniverse 渲染器微服务都使用 USD 场景配置。默认情况下,UCS 应用程序配置微服务以从 NGC 下载头像场景。但是,还有其他下载资源的方法,您也可以创建自己的资源下载器 init 容器,如资源下载器部分所述。

构建 UCS 应用程序#

rm -rf _build/animation_pipeline*
ucf_app_builder_cli app build ucs_apps/animation_pipeline.yaml ucs_apps/animation_pipeline_params.yaml -o _build/animation_pipeline

部署 UCS 应用程序#

name=animation-pipeline
namespace=$name

kubectl create namespace $namespace
kubectl create secret docker-registry ngc-docker-reg-secret --docker-server=nvcr.io --docker-username='$oauthtoken' --docker-password=$NGC_CLI_API_KEY -n $namespace
kubectl create secret generic ngc-api-key-secret --from-literal=NGC_CLI_API_KEY=$NGC_CLI_API_KEY -n $namespace

然后,启动部署

helm upgrade --install --cleanup-on-fail --namespace $namespace $name _build/animation_pipeline/ -f _build/animation_pipeline/values.yaml -f ucs_apps/animation_pipeline_values.yaml

检查 Pod 状态

watch kubectl get pods -n $namespace

启动所有 Pod 将需要长达 30 分钟。您需要等到它们都指示为就绪。

准备流式传输#

我们将创建两个独立的头像流实例。

为动画图微服务添加两个不同的流 ID

stream_id_1=$(uuidgen)
kubectl exec -n $namespace -c ms ia-animation-graph-microservice-deployment-0 -- curl -X POST -s http://127.0.0.1:8020/streams/$stream_id_1

 # If using two renderers:
stream_id_2=$(uuidgen)
kubectl exec -n $namespace -c ms ia-animation-graph-microservice-deployment-0 -- curl -X POST -s http://127.0.0.1:8020/streams/$stream_id_2

验证日志中是否存在“Sending Animation Data to output for stream_id <stream_id_#>”

kubectl logs -n $namespace -c ms ia-animation-graph-microservice-deployment-0

将流 ID 添加到 Omniverse 渲染器微服务

kubectl exec -n $namespace -c ms avatar-renderer-a-deployment-0 -- curl -X POST -s http://127.0.0.1:8021/streams/$stream_id_1

# If using two renderers:
kubectl exec -n $namespace -c ms avatar-renderer-b-deployment-0 -- curl -X POST -s http://127.0.0.1:8021/streams/$stream_id_2

验证两个渲染器微服务中都存在日志“Rendering animation data”

kubectl logs -n $namespace -c ms avatar-renderer-a-deployment-0

# If using two renderers:
kubectl logs -n $namespace -c ms avatar-renderer-b-deployment-0

设置和启动 Gstreamer#

我们将使用 Gstreamer 捕获图像和音频输出流,以可视化两个头像场景。

安装 Gstreamer 插件

sudo apt-get install gstreamer1.0-plugins-bad gstreamer1.0-libav

使用 ucs_apps/animation_pipeline_params.yaml 中指定的端口。默认端口为视频 9020/9030 和音频 9021/9031。

在各自的终端中运行以下每个命令

# Avatar stream 1
gst-launch-1.0 -v udpsrc port=9020 caps="application/x-rtp" ! rtpjitterbuffer drop-on-latency=true latency=20 ! rtph264depay ! h264parse ! avdec_h264 ! videoconvert ! fpsdisplaysink text-overlay=0 video-sink=autovideosink
gst-launch-1.0 -v udpsrc port=9021 caps="application/x-rtp,clock-rate=16000" ! rtpjitterbuffer ! rtpL16depay ! audioconvert ! autoaudiosink sync=false

# Avatar stream 2 (if using two renderers)
gst-launch-1.0 -v udpsrc port=9030 caps="application/x-rtp" ! rtpjitterbuffer drop-on-latency=true latency=20 ! rtph264depay ! h264parse ! avdec_h264 ! videoconvert ! fpsdisplaysink text-overlay=0 video-sink=autovideosink
gst-launch-1.0 -v udpsrc port=9031 caps="application/x-rtp,clock-rate=16000" ! rtpjitterbuffer ! rtpL16depay ! audioconvert ! autoaudiosink sync=false

或者,您也可以将音频和视频流一起录制到文件中

# Avatar stream 1
gst-launch-1.0 -e -v udpsrc port=9021 caps="application/x-rtp,clock-rate=16000" ! rtpjitterbuffer ! rtpL16depay ! audioconvert ! matroskamux name=mux ! filesink location="stream_id_1.mkv" udpsrc port=9020 caps="application/x-rtp" ! rtpjitterbuffer drop-on-latency=true latency=20 ! rtph264depay ! h264parse ! mux.

# Avatar stream 2 (if using two renderers)
gst-launch-1.0 -e -v udpsrc port=9031 caps="application/x-rtp,clock-rate=16000" ! rtpjitterbuffer ! rtpL16depay ! audioconvert ! matroskamux name=mux ! filesink location="stream_id_2.mkv" udpsrc port=9030 caps="application/x-rtp" ! rtpjitterbuffer drop-on-latency=true latency=20 ! rtph264depay ! h264parse ! mux.

测试动画图接口#

回到您的主终端,让我们为头像 1 设置一个新的姿势

kubectl exec -n $namespace -c ms ia-animation-graph-microservice-deployment-0 -- curl -X PUT -s http://127.0.0.1:8020/streams/$stream_id_1/animation_graphs/avatar/variables/posture_state/Talking

或更改头像的位置

kubectl exec -n $namespace -c ms ia-animation-graph-microservice-deployment-0 -- curl -X PUT -s http://127.0.0.1:8020/streams/$stream_id_1/animation_graphs/avatar/variables/position_state/Left

或启动一个手势

kubectl exec -n $namespace -c ms ia-animation-graph-microservice-deployment-0 -- curl -X PUT -s http://127.0.0.1:8020/streams/$stream_id_1/animation_graphs/avatar/variables/gesture_state/Pulling_Mime

或触发一个面部表情

kubectl exec -n $namespace -c ms ia-animation-graph-microservice-deployment-0 -- curl -X PUT -s http://127.0.0.1:8020/streams/$stream_id_1/animation_graphs/avatar/variables/facial_gesture_state/Smile

或者,在启用端口转发后,您可以浏览动画图微服务 (http://127.0.0.1:8020/docs) 或 Omniverse 渲染器微服务 (http://127.0.0.1:8021/docs) 的 OpenAPI 接口

kubectl port-forward -n $namespace ia-animation-graph-microservice-deployment-0 8020:8020
kubectl port-forward -n $namespace avatar-renderer-a-deployment-0 8021:8021

您可以在此处找到所有有效的变量值:默认动画图

测试 Audio2Face-3D#

在单独的选项卡中,激活端口转发

kubectl port-forward -n $namespace a2f-with-emotion-a2f-deployment-XXX 50010:50010
kubectl port-forward -n $namespace ia-animation-graph-microservice-deployment-0 8020:8020

请注意,Audio2Face-3D Pod 有一个随机后缀,必须在上述命令中进行调整。

现在让我们使用一个示例音频文件输入到 Audio2Face-3D,以驱动面部说话动画。

通常,您会通过其 gRPC API 将音频发送到 Audio2Face-3D。为了方便起见,一个 Python 脚本允许您通过命令行执行此操作。按照设置脚本的步骤操作。

该脚本附带一个示例音频文件,该文件与 Audio2Face-3D 兼容。运行以下命令以将示例音频文件发送到 Audio2Face-3D

注意

Audio2Face-3D 要求音频为 16KHz 单声道格式。

python3 validate.py -u 127.0.0.1:50010 -i $stream_id_1 Mark_joy.wav

提取崩溃转储#

列出保存崩溃转储的目录

kubectl exec -n $namespace -c ms avatar-renderer-a-deployment-0 -- ls -alh /home/ace/asset

将崩溃转储 (<uuid>.zip) 复制到本地文件系统

kubectl cp -n $namespace avatar-renderer-a-deployment-0:/home/ace/asset/526ab2d4-72be-4f3d-d83ad384-893d4b00.dmp.zip -c ms 526ab2d4-72be-4f3d-d83ad384-893d4b00.dmp.zip

如果需要,复制到不同的机器

scp.exe -r <username>@<hostname>:<folder_path>/*.zip .\Downloads\

更改头像场景#

要修改或切换默认头像场景,您可以使用头像配置器

下载并解压缩它,并通过运行 ./run_avatar_configurator.sh 启动它。

../../_images/avatar_configurator.jpg

一旦它成功启动(第一次启动需要更长时间来编译着色器),您就可以创建自定义的新场景并保存它。

现在,您需要将新场景上传到 NGC(请参阅将版本上传到 NGC 资源)并调整 UCS 应用程序配置中的相关链接并重新部署它。

清理:移除流#

您可以使用以下命令清理流

kubectl exec -n $namespace -c ms avatar-renderer-a-deployment-0 -- curl -X DELETE -s http://127.0.0.1:8021/streams/$stream_id_1
kubectl exec -n $namespace -c ms ia-animation-graph-microservice-deployment-0 -- curl -X DELETE -s http://127.0.0.1:8020/streams/$stream_id_1

# If using two renderers:
kubectl exec -n $namespace -c ms avatar-renderer-b-deployment-0 -- curl -X DELETE -s http://127.0.0.1:8021/streams/$stream_id_2
kubectl exec -n $namespace -c ms ia-animation-graph-microservice-deployment-0 -- curl -X DELETE -s http://127.0.0.1:8020/streams/$stream_id_2